15
15
// License along with this library; if not, write to the Free Software
16
16
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
#include "oxide_qt_web_view_adapter.h"
23
#include "base/logging.h"
24
#include "base/macros.h"
25
#include "base/memory/ref_counted.h"
26
#include "base/pickle.h"
27
#include "cc/output/compositor_frame_metadata.h"
28
#include "third_party/WebKit/public/platform/WebTopControlsState.h"
29
#include "ui/gfx/geometry/point.h"
30
#include "ui/gfx/geometry/size.h"
33
#include "qt/core/api/oxideqnewviewrequest_p.h"
34
#include "qt/core/api/oxideqwebpreferences.h"
35
#include "qt/core/api/oxideqwebpreferences_p.h"
36
#include "qt/core/browser/oxide_qt_web_context.h"
37
#include "qt/core/browser/oxide_qt_web_frame.h"
38
#include "qt/core/browser/oxide_qt_web_preferences.h"
18
#include "oxide_qt_web_view_proxy.h"
39
20
#include "qt/core/browser/oxide_qt_web_view.h"
40
#include "shared/browser/compositor/oxide_compositor_frame_handle.h"
41
#include "shared/browser/oxide_content_types.h"
42
#include "shared/browser/oxide_browser_process_main.h"
43
#include "shared/common/oxide_enum_flags.h"
45
#include "oxide_qt_web_context_adapter.h"
46
#include "oxide_qt_web_frame_adapter.h"
51
OXIDE_MAKE_ENUM_BITWISE_OPERATORS(FrameMetadataChangeFlags)
55
static const char* STATE_SERIALIZER_MAGIC_NUMBER = "oxide";
56
static uint16_t STATE_SERIALIZER_VERSION = 1;
58
blink::WebTopControlsState LocationBarModeToBlinkTopControlsState(
59
LocationBarMode mode) {
61
case LOCATION_BAR_MODE_AUTO:
62
return blink::WebTopControlsBoth;
63
case LOCATION_BAR_MODE_SHOWN:
64
return blink::WebTopControlsShown;
65
case LOCATION_BAR_MODE_HIDDEN:
66
return blink::WebTopControlsHidden;
69
return blink::WebTopControlsBoth;
75
class CompositorFrameHandleImpl : public CompositorFrameHandle {
77
CompositorFrameHandleImpl(oxide::CompositorFrameHandle* frame,
78
int location_bar_content_offset)
81
rect_ = QRect(0, location_bar_content_offset,
82
frame_->size_in_pixels().width(),
83
frame_->size_in_pixels().height());
87
virtual ~CompositorFrameHandleImpl() {}
89
CompositorFrameHandle::Type GetType() final {
91
return CompositorFrameHandle::TYPE_INVALID;
93
if (frame_->gl_frame_data()) {
94
return CompositorFrameHandle::TYPE_ACCELERATED;
96
if (frame_->image_frame_data()) {
97
return CompositorFrameHandle::TYPE_IMAGE;
99
if (frame_->software_frame_data()) {
100
return CompositorFrameHandle::TYPE_SOFTWARE;
104
return CompositorFrameHandle::TYPE_INVALID;
107
const QRect& GetRect() const final {
111
QImage GetSoftwareFrame() final {
112
DCHECK_EQ(GetType(), CompositorFrameHandle::TYPE_SOFTWARE);
114
static_cast<uchar *>(frame_->software_frame_data()->pixels()),
115
frame_->size_in_pixels().width(),
116
frame_->size_in_pixels().height(),
117
QImage::Format_ARGB32);
120
unsigned int GetAcceleratedFrameTexture() final {
121
DCHECK_EQ(GetType(), CompositorFrameHandle::TYPE_ACCELERATED);
122
return frame_->gl_frame_data()->texture_id();
125
EGLImageKHR GetImageFrame() final {
126
return frame_->image_frame_data()->image();
130
scoped_refptr<oxide::CompositorFrameHandle> frame_;
134
void WebViewAdapter::EnsurePreferences() {
135
if (view_->GetWebPreferences()) {
139
OxideQWebPreferences* p = new OxideQWebPreferences(adapterToQObject(this));
140
view_->SetWebPreferences(
141
OxideQWebPreferencesPrivate::get(p)->preferences());
144
void WebViewAdapter::RestoreState(RestoreType type, const QByteArray& state) {
146
RESTORE_CURRENT_SESSION == static_cast<RestoreType>(
147
content::NavigationController::RESTORE_CURRENT_SESSION),
148
restore_type_enums_current_doesnt_match);
150
RESTORE_LAST_SESSION_EXITED_CLEANLY == static_cast<RestoreType>(
151
content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY),
152
restore_type_enums_exited_cleanly_doesnt_match);
154
RESTORE_LAST_SESSION_CRASHED == static_cast<RestoreType>(
155
content::NavigationController::RESTORE_LAST_SESSION_CRASHED),
156
restore_type_enums_crashed_doesnt_match);
158
content::NavigationController::RestoreType restore_type =
159
static_cast<content::NavigationController::RestoreType>(type);
161
#define WARN_INVALID_DATA \
162
qWarning() << "Failed to read initial state: invalid data"
163
std::vector<sessions::SerializedNavigationEntry> entries;
164
Pickle pickle(state.data(), state.size());
165
PickleIterator i(pickle);
166
std::string magic_number;
167
if (!i.ReadString(&magic_number)) {
171
if (magic_number != STATE_SERIALIZER_MAGIC_NUMBER) {
176
if (!i.ReadUInt16(&version)) {
180
if (version != STATE_SERIALIZER_VERSION) {
185
if (!i.ReadLength(&count)) {
189
entries.resize(count);
190
for (int j = 0; j < count; ++j) {
191
sessions::SerializedNavigationEntry entry;
192
if (!entry.ReadFromPickle(&i)) {
199
if (!i.ReadInt(&index)) {
203
#undef WARN_INVALID_DATA
205
view_->SetState(restore_type, entries, index);
208
void WebViewAdapter::Initialized() {
209
DCHECK(isInitialized());
211
OxideQWebPreferences* p =
212
static_cast<WebPreferences*>(view_->GetWebPreferences())->api_handle();
214
// This will happen for a WebView created by newViewRequested, as
215
// we clone the openers preferences before the WebView is created
216
p->setParent(adapterToQObject(this));
222
void WebViewAdapter::WebPreferencesDestroyed() {
223
OxideQWebPreferences* p = new OxideQWebPreferences(adapterToQObject(this));
224
view_->SetWebPreferences(
225
OxideQWebPreferencesPrivate::get(p)->preferences());
227
OnWebPreferencesReplaced();
230
void WebViewAdapter::ScheduleUpdate() {
231
compositor_frame_.reset();
235
void WebViewAdapter::EvictCurrentFrame() {
236
compositor_frame_.reset();
237
OnEvictCurrentFrame();
240
WebViewAdapter::WebViewAdapter(QObject* q) :
242
view_(WebView::Create(this)) {}
244
WebViewAdapter::~WebViewAdapter() {}
246
void WebViewAdapter::init(bool incognito,
247
WebContextAdapter* context,
248
OxideQNewViewRequest* new_view_request,
249
const QByteArray& restoreState,
250
RestoreType restoreType) {
251
DCHECK(!isInitialized());
253
bool script_opened = false;
255
if (new_view_request) {
256
OxideQNewViewRequestPrivate* rd =
257
OxideQNewViewRequestPrivate::get(new_view_request);
259
qWarning() << "Cannot assign NewViewRequest to more than one WebView";
261
rd->view = view_->AsWeakPtr();
262
script_opened = true;
267
// Script opened webviews get initialized via another path
271
if (!restoreState.isEmpty()) {
272
RestoreState(restoreType, restoreState);
276
"No context available for WebView. If you see this when running in "
277
"single-process mode, it is possible that the default WebContext has "
278
"been deleted by the application. In single-process mode, there is only "
279
"one WebContext, and this has to live for the life of the application";
281
WebContext* c = WebContext::FromAdapter(context);
283
if (oxide::BrowserProcessMain::GetInstance()->GetProcessModel() ==
284
oxide::PROCESS_MODEL_SINGLE_PROCESS) {
286
DCHECK_EQ(c, WebContext::GetDefault());
291
oxide::WebView::Params params;
292
params.context = c->GetContext();
293
params.incognito = incognito;
295
view_->Init(¶ms);
298
QUrl WebViewAdapter::url() const {
299
return QUrl(QString::fromStdString(view_->GetURL().spec()));
302
void WebViewAdapter::setUrl(const QUrl& url) {
303
view_->SetURL(GURL(url.toString().toStdString()));
306
QString WebViewAdapter::title() const {
307
return QString::fromStdString(view_->GetTitle());
310
bool WebViewAdapter::canGoBack() const {
311
return view_->CanGoBack();
314
bool WebViewAdapter::canGoForward() const {
315
return view_->CanGoForward();
318
bool WebViewAdapter::incognito() const {
319
return view_->IsIncognito();
322
bool WebViewAdapter::loading() const {
323
return view_->IsLoading();
326
bool WebViewAdapter::fullscreen() const {
327
return view_->IsFullscreen();
330
void WebViewAdapter::setFullscreen(bool fullscreen) {
331
view_->SetIsFullscreen(fullscreen);
334
WebFrameAdapter* WebViewAdapter::rootFrame() const {
335
return WebFrameAdapter::FromWebFrame(
336
static_cast<WebFrame *>(view_->GetRootFrame()));
339
WebContextAdapter* WebViewAdapter::context() const {
340
WebContext* c = view_->GetContext();
345
return WebContextAdapter::FromWebContext(c);
348
void WebViewAdapter::wasResized() {
352
void WebViewAdapter::screenUpdated() {
353
view_->ScreenUpdated();
356
void WebViewAdapter::visibilityChanged() {
357
view_->VisibilityChanged();
360
void WebViewAdapter::handleFocusEvent(QFocusEvent* event) {
361
view_->HandleFocusEvent(event);
364
void WebViewAdapter::handleInputMethodEvent(QInputMethodEvent* event) {
365
view_->HandleInputMethodEvent(event);
368
void WebViewAdapter::handleKeyEvent(QKeyEvent* event) {
369
view_->HandleKeyEvent(event);
372
void WebViewAdapter::handleMouseEvent(QMouseEvent* event) {
373
view_->HandleMouseEvent(event);
376
void WebViewAdapter::handleTouchEvent(QTouchEvent* event) {
377
view_->HandleTouchEvent(event);
380
void WebViewAdapter::handleWheelEvent(QWheelEvent* event) {
381
view_->HandleWheelEvent(event);
384
QVariant WebViewAdapter::inputMethodQuery(Qt::InputMethodQuery query) const {
385
return view_->InputMethodQuery(query);
388
void WebViewAdapter::goBack() {
392
void WebViewAdapter::goForward() {
396
void WebViewAdapter::stop() {
400
void WebViewAdapter::reload() {
404
void WebViewAdapter::loadHtml(const QString& html, const QUrl& baseUrl) {
405
QByteArray encodedData = html.toUtf8().toPercentEncoding();
406
view_->LoadData(std::string(encodedData.constData(), encodedData.length()),
407
"text/html;charset=UTF-8",
408
GURL(baseUrl.toString().toStdString()));
411
QList<ScriptMessageHandlerAdapter*>& WebViewAdapter::messageHandlers() {
412
return message_handlers_;
415
bool WebViewAdapter::isInitialized() const {
416
return view_->GetWebContents() != nullptr;
419
int WebViewAdapter::getNavigationEntryCount() const {
420
return view_->GetNavigationEntryCount();
423
int WebViewAdapter::getNavigationCurrentEntryIndex() const {
424
return view_->GetNavigationCurrentEntryIndex();
427
void WebViewAdapter::setNavigationCurrentEntryIndex(int index) {
428
view_->SetNavigationCurrentEntryIndex(index);
431
int WebViewAdapter::getNavigationEntryUniqueID(int index) const {
432
return view_->GetNavigationEntryUniqueID(index);
435
QUrl WebViewAdapter::getNavigationEntryUrl(int index) const {
436
return QUrl(QString::fromStdString(
437
view_->GetNavigationEntryUrl(index).spec()));
440
QString WebViewAdapter::getNavigationEntryTitle(int index) const {
441
return QString::fromStdString(view_->GetNavigationEntryTitle(index));
444
QDateTime WebViewAdapter::getNavigationEntryTimestamp(int index) const {
445
return QDateTime::fromMSecsSinceEpoch(
446
view_->GetNavigationEntryTimestamp(index).ToJsTime());
449
QByteArray WebViewAdapter::currentState() const {
450
std::vector<sessions::SerializedNavigationEntry> entries = view_->GetState();
451
if (entries.size() == 0) {
455
pickle.WriteString(STATE_SERIALIZER_MAGIC_NUMBER);
456
pickle.WriteUInt16(STATE_SERIALIZER_VERSION);
457
pickle.WriteInt(entries.size());
458
std::vector<sessions::SerializedNavigationEntry>::const_iterator i;
459
static const size_t max_state_size = std::numeric_limits<uint16>::max() - 1024;
460
for (i = entries.begin(); i != entries.end(); ++i) {
461
i->WriteToPickle(max_state_size, &pickle);
463
pickle.WriteInt(view_->GetNavigationCurrentEntryIndex());
464
return QByteArray(static_cast<const char*>(pickle.data()), pickle.size());
467
OxideQWebPreferences* WebViewAdapter::preferences() {
469
return static_cast<WebPreferences*>(
470
view_->GetWebPreferences())->api_handle();
473
void WebViewAdapter::setPreferences(OxideQWebPreferences* prefs) {
474
OxideQWebPreferences* old = nullptr;
475
if (WebPreferences* o =
476
static_cast<WebPreferences *>(view_->GetWebPreferences())) {
477
old = o->api_handle();
481
prefs = new OxideQWebPreferences(adapterToQObject(this));
482
} else if (!prefs->parent()) {
483
prefs->setParent(adapterToQObject(this));
485
view_->SetWebPreferences(
486
OxideQWebPreferencesPrivate::get(prefs)->preferences());
492
if (old->parent() == adapterToQObject(this)) {
497
void WebViewAdapter::updateWebPreferences() {
498
view_->UpdateWebPreferences();
501
QPoint WebViewAdapter::compositorFrameScrollOffsetPix() {
502
gfx::Point offset = view_->GetCompositorFrameScrollOffsetPix();
503
return QPoint(offset.x(), offset.y());
506
QSize WebViewAdapter::compositorFrameContentSizePix() {
507
gfx::Size size = view_->GetCompositorFrameContentSizePix();
508
return QSize(size.width(), size.height());
511
QSize WebViewAdapter::compositorFrameViewportSizePix() {
512
gfx::Size size = view_->GetCompositorFrameViewportSizePix();
513
return QSize(size.width(), size.height());
516
QSharedPointer<CompositorFrameHandle> WebViewAdapter::compositorFrameHandle() {
517
if (!compositor_frame_) {
518
const cc::CompositorFrameMetadata& metadata =
519
view_->compositor_frame_metadata();
521
QSharedPointer<CompositorFrameHandle>(new CompositorFrameHandleImpl(
522
view_->GetCompositorFrameHandle(),
523
metadata.device_scale_factor *
524
metadata.location_bar_content_translation.y()));
527
return compositor_frame_;
530
void WebViewAdapter::didCommitCompositorFrame() {
531
view_->DidCommitCompositorFrame();
534
void WebViewAdapter::setCanTemporarilyDisplayInsecureContent(bool allow) {
535
view_->SetCanTemporarilyDisplayInsecureContent(allow);
538
void WebViewAdapter::setCanTemporarilyRunInsecureContent(bool allow) {
539
view_->SetCanTemporarilyRunInsecureContent(allow);
542
OxideQSecurityStatus* WebViewAdapter::securityStatus() {
543
return view_->qsecurity_status();
546
ContentTypeFlags WebViewAdapter::blockedContent() const {
549
static_cast<ContentTypeFlags>(oxide::CONTENT_TYPE_NONE),
550
content_type_flags_none_doesnt_match);
552
CONTENT_TYPE_MIXED_DISPLAY ==
553
static_cast<ContentTypeFlags>(oxide::CONTENT_TYPE_MIXED_DISPLAY),
554
content_type_flags_mixed_display_doesnt_match);
556
CONTENT_TYPE_MIXED_SCRIPT ==
557
static_cast<ContentTypeFlags>(oxide::CONTENT_TYPE_MIXED_SCRIPT),
558
content_type_flags_mixed_script_doesnt_match);
560
return static_cast<ContentTypeFlags>(view_->blocked_content());
563
void WebViewAdapter::prepareToClose() {
564
view_->PrepareToClose();
567
int WebViewAdapter::locationBarHeight() {
568
return view_->GetLocationBarHeightPix();
571
void WebViewAdapter::setLocationBarHeight(int height) {
572
view_->SetLocationBarHeightPix(height);
575
int WebViewAdapter::locationBarOffsetPix() {
576
return view_->GetLocationBarOffsetPix();
579
int WebViewAdapter::locationBarContentOffsetPix() {
580
return view_->GetLocationBarContentOffsetPix();
583
LocationBarMode WebViewAdapter::locationBarMode() const {
584
switch (view_->location_bar_constraints()) {
585
case blink::WebTopControlsShown:
586
return LOCATION_BAR_MODE_SHOWN;
587
case blink::WebTopControlsHidden:
588
return LOCATION_BAR_MODE_HIDDEN;
589
case blink::WebTopControlsBoth:
590
return LOCATION_BAR_MODE_AUTO;
593
return LOCATION_BAR_MODE_AUTO;
597
void WebViewAdapter::setLocationBarMode(LocationBarMode mode) {
598
view_->SetLocationBarConstraints(LocationBarModeToBlinkTopControlsState(mode));
26
WebViewProxy* WebViewProxy::create(WebViewProxyClient* client) {
27
return new WebView(client);
30
WebViewProxy::~WebViewProxy() {}
602
33
} // namespace oxide