diff options
Diffstat (limited to 'src/core/web_contents_adapter.cpp')
-rw-r--r-- | src/core/web_contents_adapter.cpp | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp new file mode 100644 index 000000000..c09fc362a --- /dev/null +++ b/src/core/web_contents_adapter.cpp @@ -0,0 +1,346 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "web_contents_adapter.h" + +#include "content_browser_client_qt.h" +#include "browser_context_qt.h" +#include "type_conversion.h" +#include "web_contents_adapter_client.h" +#include "web_contents_delegate_qt.h" +#include "web_contents_view_qt.h" +#include "web_engine_context.h" + +#include "base/values.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/page_zoom.h" +#include "content/public/common/renderer_preferences.h" + +#include <QGuiApplication> +#include <QStyleHints> +#include <QVariant> + +static const int kTestWindowWidth = 800; +static const int kTestWindowHeight = 600; + +static QVariant fromJSValue(const base::Value *result) +{ + QVariant ret; + switch (result->GetType()) { + case base::Value::TYPE_NULL: + break; + case base::Value::TYPE_BOOLEAN: + { + bool out; + if (result->GetAsBoolean(&out)) + ret.setValue(out); + break; + } + case base::Value::TYPE_INTEGER: + { + int out; + if (result->GetAsInteger(&out)) + ret.setValue(out); + break; + } + case base::Value::TYPE_DOUBLE: + { + double out; + if (result->GetAsDouble(&out)) + ret.setValue(out); + break; + } + case base::Value::TYPE_STRING: + { + base::string16 out; + if (result->GetAsString(&out)) + ret.setValue(toQt(out)); + break; + } + case base::Value::TYPE_LIST: + { + const base::ListValue *out; + if (result->GetAsList(&out)) { + QVariantList list; + list.reserve(out->GetSize()); + for (size_t i = 0; i < out->GetSize(); ++i) { + const base::Value *outVal = 0; + if (out->Get(i, &outVal) && outVal) + list.insert(i, fromJSValue(outVal)); + } + ret.setValue(list); + } + break; + } + case base::Value::TYPE_DICTIONARY: + { + const base::DictionaryValue *out; + if (result->GetAsDictionary(&out)) { + QVariantMap map; + base::DictionaryValue::Iterator it(*out); + while (!it.IsAtEnd()) { + map.insert(toQt(it.key()), fromJSValue(&it.value())); + it.Advance(); + } + ret.setValue(map); + } + break; + } + case base::Value::TYPE_BINARY: + { + const base::BinaryValue *out = static_cast<const base::BinaryValue*>(result); + QByteArray data(out->GetBuffer(), out->GetSize()); + ret.setValue(data); + break; + } + default: + Q_UNREACHABLE(); + break; + } + return ret; +} + +static void callbackOnEvaluateJS(JSCallbackBase *callback, const base::Value *result) +{ + callback->call(fromJSValue(result)); + delete callback; +} + +class WebContentsAdapterPrivate { +public: + WebContentsAdapterPrivate(WebContentsAdapterClient::RenderingMode renderingMode); + scoped_refptr<WebEngineContext> engineContext; + scoped_ptr<content::WebContents> webContents; + scoped_ptr<WebContentsDelegateQt> webContentsDelegate; + WebContentsAdapterClient *adapterClient; +}; + +WebContentsAdapterPrivate::WebContentsAdapterPrivate(WebContentsAdapterClient::RenderingMode renderingMode) + // This has to be the first thing we create, and the last we destroy. + : engineContext(WebEngineContext::currentOrCreate(renderingMode)) +{ +} + +WebContentsAdapter::WebContentsAdapter(WebContentsAdapterClient::RenderingMode renderingMode, content::WebContents *webContents) + : d_ptr(new WebContentsAdapterPrivate(renderingMode)) +{ + Q_D(WebContentsAdapter); + d->webContents.reset(webContents); +} + +WebContentsAdapter::~WebContentsAdapter() +{ +} + +void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) +{ + Q_D(WebContentsAdapter); + d->adapterClient = adapterClient; + + // Create our own if a WebContents wasn't provided at construction. + if (!d->webContents) { + content::BrowserContext* browserContext = ContentBrowserClientQt::Get()->browser_context(); + content::WebContents::CreateParams create_params(browserContext, NULL); + create_params.routing_id = MSG_ROUTING_NONE; + create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); + create_params.context = reinterpret_cast<gfx::NativeView>(adapterClient); + d->webContents.reset(content::WebContents::Create(create_params)); + } + + content::RendererPreferences* rendererPrefs = d->webContents->GetMutableRendererPrefs(); + rendererPrefs->use_custom_colors = true; + // Qt returns a flash time (the whole cycle) in ms, chromium expects just the interval in seconds + const int qtCursorFlashTime = QGuiApplication::styleHints()->cursorFlashTime(); + rendererPrefs->caret_blink_interval = 0.5 * static_cast<double>(qtCursorFlashTime) / 1000; + d->webContents->GetRenderViewHost()->SyncRendererPrefs(); + + // Create and attach a WebContentsDelegateQt to the WebContents. + d->webContentsDelegate.reset(new WebContentsDelegateQt(d->webContents.get(), adapterClient)); + + // Let the WebContent's view know about the WebContentsAdapterClient. + WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(d->webContents->GetView()); + contentsView->initialize(adapterClient); +} + +bool WebContentsAdapter::canGoBack() const +{ + Q_D(const WebContentsAdapter); + return d->webContents->GetController().CanGoBack(); +} + +bool WebContentsAdapter::canGoForward() const +{ + Q_D(const WebContentsAdapter); + return d->webContents->GetController().CanGoForward(); +} + +bool WebContentsAdapter::isLoading() const +{ + Q_D(const WebContentsAdapter); + return d->webContents->IsLoading(); +} + +void WebContentsAdapter::stop() +{ + Q_D(WebContentsAdapter); + content::NavigationController& controller = d->webContents->GetController(); + + int index = controller.GetPendingEntryIndex(); + if (index != -1) + controller.RemoveEntryAtIndex(index); + + d->webContents->GetView()->Focus(); +} + +void WebContentsAdapter::reload() +{ + Q_D(WebContentsAdapter); + d->webContents->GetController().Reload(/*checkRepost = */false); + d->webContents->GetView()->Focus(); +} + +void WebContentsAdapter::load(const QUrl &url) +{ + Q_D(WebContentsAdapter); + content::NavigationController::LoadURLParams params(toGurl(url)); + params.transition_type = content::PageTransitionFromInt(content::PAGE_TRANSITION_TYPED | content::PAGE_TRANSITION_FROM_ADDRESS_BAR); + d->webContents->GetController().LoadURLWithParams(params); + d->webContents->GetView()->Focus(); +} + +QUrl WebContentsAdapter::activeUrl() const +{ + Q_D(const WebContentsAdapter); + return toQt(d->webContents->GetVisibleURL()); +} + +QString WebContentsAdapter::pageTitle() const +{ + Q_D(const WebContentsAdapter); + content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry(); + return entry ? toQt(entry->GetTitle()) : QString(); +} + +void WebContentsAdapter::navigateToIndex(int offset) +{ + Q_D(WebContentsAdapter); + d->webContents->GetController().GoToIndex(offset); + d->webContents->GetView()->Focus(); +} + +void WebContentsAdapter::navigateToOffset(int offset) +{ + Q_D(WebContentsAdapter); + d->webContents->GetController().GoToOffset(offset); + d->webContents->GetView()->Focus(); +} + +int WebContentsAdapter::navigationEntryCount() +{ + Q_D(WebContentsAdapter); + return d->webContents->GetController().GetEntryCount(); +} + +int WebContentsAdapter::currentNavigationEntryIndex() +{ + Q_D(WebContentsAdapter); + return d->webContents->GetController().GetCurrentEntryIndex(); +} + +QUrl WebContentsAdapter::getNavigationEntryOriginalUrl(int index) +{ + Q_D(WebContentsAdapter); + content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + return entry ? toQt(entry->GetOriginalRequestURL()) : QUrl(); +} + +QUrl WebContentsAdapter::getNavigationEntryUrl(int index) +{ + Q_D(WebContentsAdapter); + content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + return entry ? toQt(entry->GetURL()) : QUrl(); +} + +QString WebContentsAdapter::getNavigationEntryTitle(int index) +{ + Q_D(WebContentsAdapter); + content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + return entry ? toQt(entry->GetTitle()) : QString(); +} + +void WebContentsAdapter::clearNavigationHistory() +{ + Q_D(WebContentsAdapter); + if (d->webContents->GetController().CanPruneAllButVisible()) + d->webContents->GetController().PruneAllButVisible(); +} + +void WebContentsAdapter::setZoomFactor(qreal factor) +{ + Q_D(WebContentsAdapter); + if (content::RenderViewHost *rvh = d->webContents->GetRenderViewHost()) + rvh->SetZoomLevel(content::ZoomFactorToZoomLevel(static_cast<double>(factor))); +} + +qreal WebContentsAdapter::currentZoomFactor() const +{ + Q_D(const WebContentsAdapter); + return static_cast<qreal>(content::ZoomLevelToZoomFactor(d->webContents->GetZoomLevel())); +} + +void WebContentsAdapter::enableInspector(bool enable) +{ + ContentBrowserClientQt::Get()->enableInspector(enable); +} + +void WebContentsAdapter::runJavaScript(const QString &javaScript, const QString &xPath, JSCallbackBase *func) +{ + Q_D(WebContentsAdapter); + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + Q_ASSERT(rvh); + if (!func) + rvh->ExecuteJavascriptInWebFrame(toString16(xPath), toString16(javaScript)); + else { + content::RenderViewHost::JavascriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, func); + rvh->ExecuteJavascriptInWebFrameCallbackResult(toString16(xPath), toString16(javaScript), callback); + } +} |