summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky <sky@chromium.org>2015-06-23 16:22:38 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-23 23:23:23 +0000
commit0c9bf63193891a0d2f5f60079214a5e7183f070b (patch)
tree745ca41693d856f17bd53b671f1a6c1ec9370e27
parentf5f91f945f8c03393460d7375f8837078f50cf85 (diff)
downloadchromium_src-0c9bf63193891a0d2f5f60079214a5e7183f070b.zip
chromium_src-0c9bf63193891a0d2f5f60079214a5e7183f070b.tar.gz
chromium_src-0c9bf63193891a0d2f5f60079214a5e7183f070b.tar.bz2
Factors OOPIFs in mandoline to own HTMLDocument class
Having to support both in the same class at the same time is too painful. I'm forking off a copy of HTMLDocument and will have it exclusively handle the OOPIFs case. When OOPIFs is ready, will then nuke the old and only have HTMLDocument again. BUG=479172,490221 TEST=none R=ben@chromium.org Review URL: https://codereview.chromium.org/1206633002 Cr-Commit-Position: refs/heads/master@{#335802}
-rw-r--r--components/html_viewer/BUILD.gn2
-rw-r--r--components/html_viewer/html_document.cc53
-rw-r--r--components/html_viewer/html_document.h18
-rw-r--r--components/html_viewer/html_document_oopif.cc497
-rw-r--r--components/html_viewer/html_document_oopif.h199
-rw-r--r--components/html_viewer/html_viewer.cc41
6 files changed, 736 insertions, 74 deletions
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn
index 9b79e91..de1e990 100644
--- a/components/html_viewer/BUILD.gn
+++ b/components/html_viewer/BUILD.gn
@@ -75,6 +75,8 @@ source_set("lib") {
"frame_tree_manager.h",
"html_document.cc",
"html_document.h",
+ "html_document_oopif.cc",
+ "html_document_oopif.h",
"media_factory.cc",
"media_factory.h",
"mock_web_blob_registry_impl.cc",
diff --git a/components/html_viewer/html_document.cc b/components/html_viewer/html_document.cc
index a68478d2..03d4d91 100644
--- a/components/html_viewer/html_document.cc
+++ b/components/html_viewer/html_document.cc
@@ -62,13 +62,6 @@ using mojo::WeakBindToRequest;
namespace html_viewer {
namespace {
-// Switch to enable out of process iframes.
-const char kOOPIF[] = "oopifs";
-
-bool EnableOOPIFs() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(kOOPIF);
-}
-
bool EnableRemoteDebugging() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
devtools_service::kRemoteDebuggingPort);
@@ -133,8 +126,7 @@ mojo::Target WebNavigationPolicyToNavigationTarget(
bool CanNavigateLocally(blink::WebFrame* frame,
const blink::WebURLRequest& request) {
// For now, we just load child frames locally.
- // TODO(sky): this can be removed once we transition to oopifs.
- if (!EnableOOPIFs() && frame->parent())
+ if (frame->parent())
return true;
// If we have extraData() it means we already have the url response
@@ -164,11 +156,8 @@ HTMLDocument::HTMLDocument(mojo::ApplicationImpl* html_document_app,
root_(nullptr),
view_manager_client_factory_(html_document_app->shell(), this),
setup_(setup),
- frame_tree_manager_binding_(&frame_tree_manager_),
delete_callback_(delete_callback) {
connection->AddService(
- static_cast<mojo::InterfaceFactory<mandoline::FrameTreeClient>*>(this));
- connection->AddService(
static_cast<InterfaceFactory<mojo::AxProvider>*>(this));
connection->AddService(&view_manager_client_factory_);
@@ -225,12 +214,6 @@ void HTMLDocument::Create(mojo::ApplicationConnection* connection,
}
}
-void HTMLDocument::Create(
- mojo::ApplicationConnection* connection,
- mojo::InterfaceRequest<mandoline::FrameTreeClient> request) {
- frame_tree_manager_binding_.Bind(request.Pass());
-}
-
void HTMLDocument::Load(URLResponsePtr response) {
DCHECK(!web_view_);
web_view_ = blink::WebView::create(this);
@@ -265,15 +248,6 @@ void HTMLDocument::Load(URLResponsePtr response) {
UpdateFocus();
}
-void HTMLDocument::ConvertLocalFrameToRemoteFrame(blink::WebLocalFrame* frame) {
- mojo::View* view = frame_to_view_[frame].view;
- // TODO(sky): this leaks. Fix it.
- blink::WebRemoteFrame* remote_frame = blink::WebRemoteFrame::create(
- frame_to_view_[frame].scope, new RemoteFrameClientImpl(view));
- remote_frame->initializeFromFrame(frame);
- frame->swap(remote_frame);
-}
-
void HTMLDocument::UpdateWebviewSizeFromViewSize() {
web_view_->setDeviceScaleFactor(setup_->device_pixel_ratio());
const gfx::Size size_in_pixels(root_->bounds().width, root_->bounds().height);
@@ -347,18 +321,6 @@ blink::WebFrame* HTMLDocument::createChildFrame(
blink::WebSandboxFlags sandboxFlags) {
blink::WebLocalFrame* child_frame = blink::WebLocalFrame::create(scope, this);
parent->appendChild(child_frame);
- if (EnableOOPIFs()) {
- // Create the view that will house the frame now. We embed only once we know
- // the url.
- mojo::View* child_frame_view = root_->view_manager()->CreateView();
- child_frame_view->SetVisible(true);
- root_->AddChild(child_frame_view);
-
- ChildFrameData child_frame_data;
- child_frame_data.view = child_frame_view;
- child_frame_data.scope = scope;
- frame_to_view_[child_frame] = child_frame_data;
- }
return child_frame;
}
@@ -394,19 +356,6 @@ blink::WebNavigationPolicy HTMLDocument::decidePolicyForNavigation(
}
std::string frame_name = info.frame ? info.frame->assignedName().utf8() : "";
- if (info.frame->parent() && EnableOOPIFs()) {
- mojo::View* view = frame_to_view_[info.frame].view;
- mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest);
- view->EmbedAllowingReembed(url_request.Pass());
- // TODO(sky): I tried swapping the frame types here, but that resulted in
- // the view never getting sized. Figure out why.
- // TODO(sky): there are timing conditions here, and we should only do this
- // once.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&HTMLDocument::ConvertLocalFrameToRemoteFrame,
- base::Unretained(this), info.frame));
- return blink::WebNavigationPolicyIgnore;
- }
if (CanNavigateLocally(info.frame, info.urlRequest))
return info.defaultPolicy;
diff --git a/components/html_viewer/html_document.h b/components/html_viewer/html_document.h
index c9dc997..4c9845d 100644
--- a/components/html_viewer/html_document.h
+++ b/components/html_viewer/html_document.h
@@ -5,19 +5,16 @@
#ifndef COMPONENTS_HTML_VIEWER_HTML_DOCUMENT_H_
#define COMPONENTS_HTML_VIEWER_HTML_DOCUMENT_H_
-#include <map>
#include <set>
#include "base/callback.h"
#include "base/macros.h"
#include "components/html_viewer/ax_provider_impl.h"
-#include "components/html_viewer/frame_tree_manager.h"
#include "components/html_viewer/touch_handler.h"
#include "components/view_manager/public/cpp/view_manager_client_factory.h"
#include "components/view_manager/public/cpp/view_manager_delegate.h"
#include "components/view_manager/public/cpp/view_observer.h"
#include "mandoline/services/navigation/public/interfaces/navigation.mojom.h"
-#include "mandoline/tab/public/interfaces/frame_tree.mojom.h"
#include "mojo/application/public/cpp/app_lifetime_helper.h"
#include "mojo/application/public/cpp/interface_factory.h"
#include "mojo/application/public/cpp/lazy_interface_ptr.h"
@@ -55,8 +52,7 @@ class HTMLDocument : public blink::WebViewClient,
public blink::WebFrameClient,
public mojo::ViewManagerDelegate,
public mojo::ViewObserver,
- public mojo::InterfaceFactory<mojo::AxProvider>,
- public mojo::InterfaceFactory<mandoline::FrameTreeClient> {
+ public mojo::InterfaceFactory<mojo::AxProvider> {
public:
using DeleteCallback = base::Callback<void(HTMLDocument*)>;
@@ -80,8 +76,6 @@ class HTMLDocument : public blink::WebViewClient,
blink::WebTreeScopeType scope;
};
- using FrameToViewMap = std::map<blink::WebLocalFrame*, ChildFrameData>;
-
~HTMLDocument() override;
// Updates the size and scale factor of the webview and related classes from
@@ -145,11 +139,6 @@ class HTMLDocument : public blink::WebViewClient,
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<mojo::AxProvider> request) override;
- // mojo::InterfaceFactory<mandoline::FrameTreeClient>
- void Create(
- mojo::ApplicationConnection* connection,
- mojo::InterfaceRequest<mandoline::FrameTreeClient> request) override;
-
void Load(mojo::URLResponsePtr response);
// Converts a WebLocalFrame to a WebRemoteFrame. Used once we know the
@@ -180,11 +169,6 @@ class HTMLDocument : public blink::WebViewClient,
scoped_ptr<TouchHandler> touch_handler_;
- FrameToViewMap frame_to_view_;
-
- FrameTreeManager frame_tree_manager_;
- mojo::Binding<mandoline::FrameTreeClient> frame_tree_manager_binding_;
-
scoped_ptr<DevToolsAgentImpl> devtools_agent_;
DeleteCallback delete_callback_;
diff --git a/components/html_viewer/html_document_oopif.cc b/components/html_viewer/html_document_oopif.cc
new file mode 100644
index 0000000..f4ec3808
--- /dev/null
+++ b/components/html_viewer/html_document_oopif.cc
@@ -0,0 +1,497 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/html_viewer/html_document_oopif.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/thread_task_runner_handle.h"
+#include "components/devtools_service/public/cpp/switches.h"
+#include "components/html_viewer/blink_input_events_type_converters.h"
+#include "components/html_viewer/blink_url_request_type_converters.h"
+#include "components/html_viewer/devtools_agent_impl.h"
+#include "components/html_viewer/media_factory.h"
+#include "components/html_viewer/setup.h"
+#include "components/html_viewer/web_layer_tree_view_impl.h"
+#include "components/html_viewer/web_storage_namespace_impl.h"
+#include "components/html_viewer/web_url_loader_impl.h"
+#include "components/view_manager/public/cpp/view.h"
+#include "components/view_manager/public/cpp/view_manager.h"
+#include "components/view_manager/public/cpp/view_property.h"
+#include "components/view_manager/public/interfaces/surfaces.mojom.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/application/public/cpp/connect.h"
+#include "mojo/application/public/interfaces/shell.mojom.h"
+#include "mojo/converters/geometry/geometry_type_converters.h"
+#include "skia/ext/refptr.h"
+#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
+#include "third_party/WebKit/public/web/WebConsoleMessage.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebRemoteFrame.h"
+#include "third_party/WebKit/public/web/WebRemoteFrameClient.h"
+#include "third_party/WebKit/public/web/WebScriptSource.h"
+#include "third_party/WebKit/public/web/WebSettings.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/gfx/geometry/dip_util.h"
+#include "ui/gfx/geometry/size.h"
+
+using blink::WebString;
+using mojo::AxProvider;
+using mojo::Rect;
+using mojo::ServiceProviderPtr;
+using mojo::URLResponsePtr;
+using mojo::View;
+using mojo::ViewManager;
+using mojo::WeakBindToRequest;
+
+namespace html_viewer {
+namespace {
+
+bool EnableRemoteDebugging() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ devtools_service::kRemoteDebuggingPort);
+}
+
+// WebRemoteFrameClient implementation used for OOPIFs.
+// TODO(sky): this needs to talk to browser by way of an interface.
+class RemoteFrameClientImpl : public blink::WebRemoteFrameClient {
+ public:
+ explicit RemoteFrameClientImpl(mojo::View* view) : view_(view) {}
+ ~RemoteFrameClientImpl() {}
+
+ // WebRemoteFrameClient methods:
+ virtual void postMessageEvent(blink::WebLocalFrame* source_frame,
+ blink::WebRemoteFrame* target_frame,
+ blink::WebSecurityOrigin target_origin,
+ blink::WebDOMMessageEvent event) {}
+ virtual void initializeChildFrame(const blink::WebRect& frame_rect,
+ float scale_factor) {
+ mojo::Rect rect;
+ rect.x = frame_rect.x;
+ rect.y = frame_rect.y;
+ rect.width = frame_rect.width;
+ rect.height = frame_rect.height;
+ view_->SetBounds(rect);
+ }
+ virtual void navigate(const blink::WebURLRequest& request,
+ bool should_replace_current_entry) {}
+ virtual void reload(bool ignore_cache, bool is_client_redirect) {}
+
+ virtual void forwardInputEvent(const blink::WebInputEvent* event) {}
+
+ private:
+ mojo::View* const view_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoteFrameClientImpl);
+};
+
+void ConfigureSettings(blink::WebSettings* settings) {
+ settings->setCookieEnabled(true);
+ settings->setDefaultFixedFontSize(13);
+ settings->setDefaultFontSize(16);
+ settings->setLoadsImagesAutomatically(true);
+ settings->setJavaScriptEnabled(true);
+}
+
+mojo::Target WebNavigationPolicyToNavigationTarget(
+ blink::WebNavigationPolicy policy) {
+ switch (policy) {
+ case blink::WebNavigationPolicyCurrentTab:
+ return mojo::TARGET_SOURCE_NODE;
+ case blink::WebNavigationPolicyNewBackgroundTab:
+ case blink::WebNavigationPolicyNewForegroundTab:
+ case blink::WebNavigationPolicyNewWindow:
+ case blink::WebNavigationPolicyNewPopup:
+ return mojo::TARGET_NEW_NODE;
+ default:
+ return mojo::TARGET_DEFAULT;
+ }
+}
+
+bool CanNavigateLocally(blink::WebFrame* frame,
+ const blink::WebURLRequest& request) {
+ // If we have extraData() it means we already have the url response
+ // (presumably because we are being called via Navigate()). In that case we
+ // can go ahead and navigate locally.
+ if (request.extraData())
+ return true;
+
+ // Otherwise we don't know if we're the right app to handle this request. Ask
+ // host to do the navigation for us.
+ return false;
+}
+
+} // namespace
+
+HTMLDocumentOOPIF::HTMLDocumentOOPIF(mojo::ApplicationImpl* html_document_app,
+ mojo::ApplicationConnection* connection,
+ URLResponsePtr response,
+ Setup* setup,
+ const DeleteCallback& delete_callback)
+ : app_refcount_(
+ html_document_app->app_lifetime_helper()->CreateAppRefCount()),
+ html_document_app_(html_document_app),
+ response_(response.Pass()),
+ navigator_host_(connection->GetServiceProvider()),
+ web_view_(nullptr),
+ root_(nullptr),
+ view_manager_client_factory_(html_document_app->shell(), this),
+ setup_(setup),
+ frame_tree_manager_binding_(&frame_tree_manager_),
+ delete_callback_(delete_callback) {
+ connection->AddService(
+ static_cast<mojo::InterfaceFactory<mandoline::FrameTreeClient>*>(this));
+ connection->AddService(
+ static_cast<InterfaceFactory<mojo::AxProvider>*>(this));
+ connection->AddService(&view_manager_client_factory_);
+
+ if (setup_->did_init())
+ Load(response_.Pass());
+}
+
+void HTMLDocumentOOPIF::Destroy() {
+ // See comment in header for a description of lifetime.
+ if (root_) {
+ // Deleting the ViewManager calls back to OnViewManagerDestroyed() and
+ // triggers deletion.
+ delete root_->view_manager();
+ } else {
+ delete this;
+ }
+}
+
+HTMLDocumentOOPIF::~HTMLDocumentOOPIF() {
+ delete_callback_.Run(this);
+
+ STLDeleteElements(&ax_providers_);
+ STLDeleteElements(&ax_provider_requests_);
+
+ if (web_view_)
+ web_view_->close();
+ if (root_)
+ root_->RemoveObserver(this);
+}
+
+void HTMLDocumentOOPIF::OnEmbed(View* root) {
+ DCHECK(!setup_->is_headless());
+ root_ = root;
+ root_->AddObserver(this);
+ UpdateFocus();
+
+ InitSetupAndLoadIfNecessary();
+}
+
+void HTMLDocumentOOPIF::OnViewManagerDestroyed(ViewManager* view_manager) {
+ delete this;
+}
+
+void HTMLDocumentOOPIF::Create(mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<AxProvider> request) {
+ if (!did_finish_load_) {
+ // Cache AxProvider interface requests until the document finishes loading.
+ auto cached_request = new mojo::InterfaceRequest<AxProvider>();
+ *cached_request = request.Pass();
+ ax_provider_requests_.insert(cached_request);
+ } else {
+ ax_providers_.insert(new AxProviderImpl(web_view_, request.Pass()));
+ }
+}
+
+void HTMLDocumentOOPIF::Create(
+ mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<mandoline::FrameTreeClient> request) {
+ frame_tree_manager_binding_.Bind(request.Pass());
+}
+
+void HTMLDocumentOOPIF::Load(URLResponsePtr response) {
+ DCHECK(!web_view_);
+ web_view_ = blink::WebView::create(this);
+ touch_handler_.reset(new TouchHandler(web_view_));
+ web_layer_tree_view_impl_->set_widget(web_view_);
+ ConfigureSettings(web_view_->settings());
+
+ blink::WebLocalFrame* main_frame =
+ blink::WebLocalFrame::create(blink::WebTreeScopeType::Document, this);
+ web_view_->setMainFrame(main_frame);
+
+ // TODO(yzshen): http://crbug.com/498986 Creating DevToolsAgentImpl instances
+ // causes html_viewer_apptests flakiness currently. Before we fix that we
+ // cannot enable remote debugging (which is required by Telemetry tests) on
+ // the bots.
+ if (EnableRemoteDebugging()) {
+ devtools_agent_.reset(
+ new DevToolsAgentImpl(main_frame, html_document_app_->shell()));
+ }
+
+ GURL url(response->url);
+
+ WebURLRequestExtraData* extra_data = new WebURLRequestExtraData;
+ extra_data->synthetic_response = response.Pass();
+
+ blink::WebURLRequest web_request;
+ web_request.initialize();
+ web_request.setURL(url);
+ web_request.setExtraData(extra_data);
+
+ web_view_->mainFrame()->loadRequest(web_request);
+ UpdateFocus();
+}
+
+void HTMLDocumentOOPIF::ConvertLocalFrameToRemoteFrame(
+ blink::WebLocalFrame* frame) {
+ mojo::View* view = frame_to_view_[frame].view;
+ // TODO(sky): this leaks. Fix it.
+ blink::WebRemoteFrame* remote_frame = blink::WebRemoteFrame::create(
+ frame_to_view_[frame].scope, new RemoteFrameClientImpl(view));
+ remote_frame->initializeFromFrame(frame);
+ frame->swap(remote_frame);
+}
+
+void HTMLDocumentOOPIF::UpdateWebviewSizeFromViewSize() {
+ web_view_->setDeviceScaleFactor(setup_->device_pixel_ratio());
+ const gfx::Size size_in_pixels(root_->bounds().width, root_->bounds().height);
+ const gfx::Size size_in_dips = gfx::ConvertSizeToDIP(
+ root_->viewport_metrics().device_pixel_ratio, size_in_pixels);
+ web_view_->resize(
+ blink::WebSize(size_in_dips.width(), size_in_dips.height()));
+ web_layer_tree_view_impl_->setViewportSize(size_in_pixels);
+}
+
+void HTMLDocumentOOPIF::InitSetupAndLoadIfNecessary() {
+ DCHECK(root_);
+ if (root_->viewport_metrics().device_pixel_ratio == 0.f)
+ return;
+
+ if (!web_view_) {
+ setup_->InitIfNecessary(
+ root_->viewport_metrics().size_in_pixels.To<gfx::Size>(),
+ root_->viewport_metrics().device_pixel_ratio);
+ Load(response_.Pass());
+ }
+
+ UpdateWebviewSizeFromViewSize();
+ web_layer_tree_view_impl_->set_view(root_);
+}
+
+blink::WebStorageNamespace* HTMLDocumentOOPIF::createSessionStorageNamespace() {
+ return new WebStorageNamespaceImpl();
+}
+
+void HTMLDocumentOOPIF::initializeLayerTreeView() {
+ if (setup_->is_headless()) {
+ web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl(
+ setup_->compositor_thread(), nullptr, nullptr, nullptr, nullptr));
+ return;
+ }
+
+ mojo::URLRequestPtr request(mojo::URLRequest::New());
+ request->url = mojo::String::From("mojo:surfaces_service");
+ mojo::SurfacePtr surface;
+ html_document_app_->ConnectToService(request.Pass(), &surface);
+
+ // TODO(jamesr): Should be mojo:gpu_service
+ mojo::URLRequestPtr request2(mojo::URLRequest::New());
+ request2->url = mojo::String::From("mojo:view_manager");
+ mojo::GpuPtr gpu_service;
+ html_document_app_->ConnectToService(request2.Pass(), &gpu_service);
+ web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl(
+ setup_->compositor_thread(), setup_->gpu_memory_buffer_manager(),
+ setup_->raster_thread_helper()->task_graph_runner(), surface.Pass(),
+ gpu_service.Pass()));
+}
+
+blink::WebLayerTreeView* HTMLDocumentOOPIF::layerTreeView() {
+ return web_layer_tree_view_impl_.get();
+}
+
+blink::WebMediaPlayer* HTMLDocumentOOPIF::createMediaPlayer(
+ blink::WebLocalFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client,
+ blink::WebContentDecryptionModule* initial_cdm) {
+ return setup_->media_factory()->CreateMediaPlayer(
+ frame, url, client, initial_cdm, html_document_app_->shell());
+}
+
+blink::WebFrame* HTMLDocumentOOPIF::createChildFrame(
+ blink::WebLocalFrame* parent,
+ blink::WebTreeScopeType scope,
+ const blink::WebString& frameName,
+ blink::WebSandboxFlags sandboxFlags) {
+ blink::WebLocalFrame* child_frame = blink::WebLocalFrame::create(scope, this);
+ parent->appendChild(child_frame);
+ // Create the view that will house the frame now. We embed only once we know
+ // the url.
+ mojo::View* child_frame_view = root_->view_manager()->CreateView();
+ child_frame_view->SetVisible(true);
+ root_->AddChild(child_frame_view);
+
+ ChildFrameData child_frame_data;
+ child_frame_data.view = child_frame_view;
+ child_frame_data.scope = scope;
+ frame_to_view_[child_frame] = child_frame_data;
+ return child_frame;
+}
+
+void HTMLDocumentOOPIF::frameDetached(blink::WebFrame* frame) {
+ frameDetached(frame, DetachType::Remove);
+}
+
+void HTMLDocumentOOPIF::frameDetached(blink::WebFrame* frame, DetachType type) {
+ DCHECK(type == DetachType::Remove);
+ if (frame->parent())
+ frame->parent()->removeChild(frame);
+
+ if (devtools_agent_ && frame == devtools_agent_->frame())
+ devtools_agent_.reset();
+
+ // |frame| is invalid after here.
+ frame->close();
+}
+
+blink::WebCookieJar* HTMLDocumentOOPIF::cookieJar(blink::WebLocalFrame* frame) {
+ // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
+ // Either it should, as it once did, or we should find another solution here.
+ return blink::Platform::current()->cookieJar();
+}
+
+blink::WebNavigationPolicy HTMLDocumentOOPIF::decidePolicyForNavigation(
+ const NavigationPolicyInfo& info) {
+ // TODO(yzshen): Remove this check once the browser is able to navigate an
+ // existing html_viewer instance and about:blank page support is ready.
+ if (devtools_agent_ && devtools_agent_->frame() == info.frame &&
+ devtools_agent_->handling_page_navigate_request()) {
+ return info.defaultPolicy;
+ }
+
+ std::string frame_name = info.frame ? info.frame->assignedName().utf8() : "";
+ if (info.frame->parent()) {
+ mojo::View* view = frame_to_view_[info.frame].view;
+ mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest);
+ view->EmbedAllowingReembed(url_request.Pass());
+ // TODO(sky): I tried swapping the frame types here, but that resulted in
+ // the view never getting sized. Figure out why.
+ // TODO(sky): there are timing conditions here, and we should only do this
+ // once.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&HTMLDocumentOOPIF::ConvertLocalFrameToRemoteFrame,
+ base::Unretained(this), info.frame));
+ return blink::WebNavigationPolicyIgnore;
+ }
+
+ if (CanNavigateLocally(info.frame, info.urlRequest))
+ return info.defaultPolicy;
+
+ if (navigator_host_.get()) {
+ mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest);
+ navigator_host_->RequestNavigate(
+ WebNavigationPolicyToNavigationTarget(info.defaultPolicy),
+ url_request.Pass());
+ }
+
+ return blink::WebNavigationPolicyIgnore;
+}
+
+void HTMLDocumentOOPIF::didAddMessageToConsole(
+ const blink::WebConsoleMessage& message,
+ const blink::WebString& source_name,
+ unsigned source_line,
+ const blink::WebString& stack_trace) {
+ VLOG(1) << "[" << source_name.utf8() << "(" << source_line << ")] "
+ << message.text.utf8();
+}
+
+void HTMLDocumentOOPIF::didFinishLoad(blink::WebLocalFrame* frame) {
+ // TODO(msw): Notify AxProvider clients of updates on child frame loads.
+ did_finish_load_ = true;
+ // Bind any pending AxProviderImpl interface requests.
+ for (auto it : ax_provider_requests_)
+ ax_providers_.insert(new AxProviderImpl(web_view_, it->Pass()));
+ STLDeleteElements(&ax_provider_requests_);
+}
+
+void HTMLDocumentOOPIF::didNavigateWithinPage(
+ blink::WebLocalFrame* frame,
+ const blink::WebHistoryItem& history_item,
+ blink::WebHistoryCommitType commit_type) {
+ if (navigator_host_.get())
+ navigator_host_->DidNavigateLocally(history_item.urlString().utf8());
+}
+
+blink::WebEncryptedMediaClient* HTMLDocumentOOPIF::encryptedMediaClient() {
+ return setup_->media_factory()->GetEncryptedMediaClient();
+}
+
+void HTMLDocumentOOPIF::OnViewBoundsChanged(View* view,
+ const Rect& old_bounds,
+ const Rect& new_bounds) {
+ DCHECK_EQ(view, root_);
+ UpdateWebviewSizeFromViewSize();
+}
+
+void HTMLDocumentOOPIF::OnViewViewportMetricsChanged(
+ mojo::View* view,
+ const mojo::ViewportMetrics& old_metrics,
+ const mojo::ViewportMetrics& new_metrics) {
+ InitSetupAndLoadIfNecessary();
+}
+
+void HTMLDocumentOOPIF::OnViewDestroyed(View* view) {
+ DCHECK_EQ(view, root_);
+ root_ = nullptr;
+}
+
+void HTMLDocumentOOPIF::OnViewInputEvent(View* view,
+ const mojo::EventPtr& event) {
+ if (event->pointer_data) {
+ // Blink expects coordintes to be in DIPs.
+ event->pointer_data->x /= setup_->device_pixel_ratio();
+ event->pointer_data->y /= setup_->device_pixel_ratio();
+ event->pointer_data->screen_x /= setup_->device_pixel_ratio();
+ event->pointer_data->screen_y /= setup_->device_pixel_ratio();
+ }
+
+ if ((event->action == mojo::EVENT_TYPE_POINTER_DOWN ||
+ event->action == mojo::EVENT_TYPE_POINTER_UP ||
+ event->action == mojo::EVENT_TYPE_POINTER_CANCEL ||
+ event->action == mojo::EVENT_TYPE_POINTER_MOVE) &&
+ event->pointer_data->kind == mojo::POINTER_KIND_TOUCH) {
+ touch_handler_->OnTouchEvent(*event);
+ return;
+ }
+ scoped_ptr<blink::WebInputEvent> web_event =
+ event.To<scoped_ptr<blink::WebInputEvent>>();
+ if (web_event)
+ web_view_->handleInputEvent(*web_event);
+}
+
+void HTMLDocumentOOPIF::OnViewFocusChanged(mojo::View* gained_focus,
+ mojo::View* lost_focus) {
+ UpdateFocus();
+}
+
+void HTMLDocumentOOPIF::UpdateFocus() {
+ if (!web_view_)
+ return;
+ bool is_focused = root_ && root_->HasFocus();
+ web_view_->setFocus(is_focused);
+ web_view_->setIsActive(is_focused);
+}
+
+} // namespace html_viewer
diff --git a/components/html_viewer/html_document_oopif.h b/components/html_viewer/html_document_oopif.h
new file mode 100644
index 0000000..989992c
--- /dev/null
+++ b/components/html_viewer/html_document_oopif.h
@@ -0,0 +1,199 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_HTML_VIEWER_HTML_DOCUMENT_OOPIF_H_
+#define COMPONENTS_HTML_VIEWER_HTML_DOCUMENT_OOPIF_H_
+
+#include <map>
+#include <set>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "components/html_viewer/ax_provider_impl.h"
+#include "components/html_viewer/frame_tree_manager.h"
+#include "components/html_viewer/touch_handler.h"
+#include "components/view_manager/public/cpp/view_manager_client_factory.h"
+#include "components/view_manager/public/cpp/view_manager_delegate.h"
+#include "components/view_manager/public/cpp/view_observer.h"
+#include "mandoline/services/navigation/public/interfaces/navigation.mojom.h"
+#include "mandoline/tab/public/interfaces/frame_tree.mojom.h"
+#include "mojo/application/public/cpp/app_lifetime_helper.h"
+#include "mojo/application/public/cpp/interface_factory.h"
+#include "mojo/application/public/cpp/lazy_interface_ptr.h"
+#include "mojo/application/public/cpp/service_provider_impl.h"
+#include "mojo/application/public/interfaces/application.mojom.h"
+#include "mojo/application/public/interfaces/content_handler.mojom.h"
+#include "mojo/services/network/public/interfaces/url_loader.mojom.h"
+#include "third_party/WebKit/public/web/WebFrameClient.h"
+#include "third_party/WebKit/public/web/WebSandboxFlags.h"
+#include "third_party/WebKit/public/web/WebViewClient.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace mojo {
+class ViewManager;
+class View;
+}
+
+namespace html_viewer {
+
+class AxProviderImpl;
+class DevToolsAgentImpl;
+class Setup;
+class WebLayerTreeViewImpl;
+
+// A view for a single HTML document.
+//
+// HTMLDocument is deleted in one of two ways:
+// . When the View the HTMLDocument is embedded in is destroyed.
+// . Explicitly by way of Destroy().
+class HTMLDocumentOOPIF
+ : public blink::WebViewClient,
+ public blink::WebFrameClient,
+ public mojo::ViewManagerDelegate,
+ public mojo::ViewObserver,
+ public mojo::InterfaceFactory<mojo::AxProvider>,
+ public mojo::InterfaceFactory<mandoline::FrameTreeClient> {
+ public:
+ using DeleteCallback = base::Callback<void(HTMLDocumentOOPIF*)>;
+
+ // Load a new HTMLDocumentOOPIF with |response|.
+ // |html_document_app| is the application this app was created in, and
+ // |connection| the specific connection triggering this new instance.
+ // |setup| is used to obtain init type state (such as resources).
+ HTMLDocumentOOPIF(mojo::ApplicationImpl* html_document_app,
+ mojo::ApplicationConnection* connection,
+ mojo::URLResponsePtr response,
+ Setup* setup,
+ const DeleteCallback& delete_callback);
+
+ // Deletes this object.
+ void Destroy();
+
+ private:
+ // Data associated with a child iframe.
+ struct ChildFrameData {
+ mojo::View* view;
+ blink::WebTreeScopeType scope;
+ };
+
+ using FrameToViewMap = std::map<blink::WebLocalFrame*, ChildFrameData>;
+
+ ~HTMLDocumentOOPIF() override;
+
+ // Updates the size and scale factor of the webview and related classes from
+ // |root_|.
+ void UpdateWebviewSizeFromViewSize();
+
+ void InitSetupAndLoadIfNecessary();
+
+ // WebViewClient methods:
+ virtual blink::WebStorageNamespace* createSessionStorageNamespace();
+
+ // WebWidgetClient methods:
+ void initializeLayerTreeView() override;
+ blink::WebLayerTreeView* layerTreeView() override;
+
+ // WebFrameClient methods:
+ virtual blink::WebMediaPlayer* createMediaPlayer(
+ blink::WebLocalFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client,
+ blink::WebContentDecryptionModule* initial_cdm);
+ virtual blink::WebFrame* createChildFrame(
+ blink::WebLocalFrame* parent,
+ blink::WebTreeScopeType scope,
+ const blink::WebString& frameName,
+ blink::WebSandboxFlags sandboxFlags);
+ virtual void frameDetached(blink::WebFrame* frame);
+ virtual void frameDetached(blink::WebFrame* frame, DetachType type);
+ virtual blink::WebCookieJar* cookieJar(blink::WebLocalFrame* frame);
+ virtual blink::WebNavigationPolicy decidePolicyForNavigation(
+ const NavigationPolicyInfo& info);
+
+ virtual void didAddMessageToConsole(const blink::WebConsoleMessage& message,
+ const blink::WebString& source_name,
+ unsigned source_line,
+ const blink::WebString& stack_trace);
+ virtual void didFinishLoad(blink::WebLocalFrame* frame);
+ virtual void didNavigateWithinPage(blink::WebLocalFrame* frame,
+ const blink::WebHistoryItem& history_item,
+ blink::WebHistoryCommitType commit_type);
+ virtual blink::WebEncryptedMediaClient* encryptedMediaClient();
+
+ // ViewManagerDelegate methods:
+ void OnEmbed(mojo::View* root) override;
+ void OnViewManagerDestroyed(mojo::ViewManager* view_manager) override;
+
+ // ViewObserver methods:
+ void OnViewBoundsChanged(mojo::View* view,
+ const mojo::Rect& old_bounds,
+ const mojo::Rect& new_bounds) override;
+ void OnViewViewportMetricsChanged(
+ mojo::View* view,
+ const mojo::ViewportMetrics& old_metrics,
+ const mojo::ViewportMetrics& new_metrics) override;
+ void OnViewDestroyed(mojo::View* view) override;
+ void OnViewInputEvent(mojo::View* view, const mojo::EventPtr& event) override;
+ void OnViewFocusChanged(mojo::View* gained_focus,
+ mojo::View* lost_focus) override;
+
+ // mojo::InterfaceFactory<mojo::AxProvider>
+ void Create(mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<mojo::AxProvider> request) override;
+
+ // mojo::InterfaceFactory<mandoline::FrameTreeClient>
+ void Create(
+ mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<mandoline::FrameTreeClient> request) override;
+
+ void Load(mojo::URLResponsePtr response);
+
+ // Converts a WebLocalFrame to a WebRemoteFrame. Used once we know the
+ // url of a frame to trigger the navigation.
+ void ConvertLocalFrameToRemoteFrame(blink::WebLocalFrame* frame);
+
+ // Updates the focus state of |web_view_| based on the focus state of |root_|.
+ void UpdateFocus();
+
+ scoped_ptr<mojo::AppRefCount> app_refcount_;
+ mojo::ApplicationImpl* html_document_app_;
+ mojo::URLResponsePtr response_;
+ mojo::LazyInterfacePtr<mojo::NavigatorHost> navigator_host_;
+ blink::WebView* web_view_;
+ mojo::View* root_;
+ mojo::ViewManagerClientFactory view_manager_client_factory_;
+ scoped_ptr<WebLayerTreeViewImpl> web_layer_tree_view_impl_;
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_;
+
+ // HTMLDocumentOOPIF owns these pointers; binding requests after document
+ // load.
+ std::set<mojo::InterfaceRequest<mojo::AxProvider>*> ax_provider_requests_;
+ std::set<AxProviderImpl*> ax_providers_;
+
+ // A flag set on didFinishLoad.
+ bool did_finish_load_ = false;
+
+ Setup* setup_;
+
+ scoped_ptr<TouchHandler> touch_handler_;
+
+ FrameToViewMap frame_to_view_;
+
+ FrameTreeManager frame_tree_manager_;
+ mojo::Binding<mandoline::FrameTreeClient> frame_tree_manager_binding_;
+
+ scoped_ptr<DevToolsAgentImpl> devtools_agent_;
+
+ DeleteCallback delete_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(HTMLDocumentOOPIF);
+};
+
+} // namespace html_viewer
+
+#endif // COMPONENTS_HTML_VIEWER_HTML_DOCUMENT_OOPIF_H_
diff --git a/components/html_viewer/html_viewer.cc b/components/html_viewer/html_viewer.cc
index fb5cfeb..f4cb7a5 100644
--- a/components/html_viewer/html_viewer.cc
+++ b/components/html_viewer/html_viewer.cc
@@ -12,6 +12,7 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/html_viewer/html_document.h"
+#include "components/html_viewer/html_document_oopif.h"
#include "components/html_viewer/setup.h"
#include "mojo/application/public/cpp/application_connection.h"
#include "mojo/application/public/cpp/application_delegate.h"
@@ -40,6 +41,15 @@ using mojo::URLLoaderPtr;
using mojo::URLResponsePtr;
namespace html_viewer {
+namespace {
+
+// Switch to enable out of process iframes.
+const char kOOPIF[] = "oopifs";
+
+bool EnableOOPIFs() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(kOOPIF);
+}
+}
class HTMLViewer;
@@ -68,6 +78,10 @@ class HTMLDocumentApplicationDelegate : public mojo::ApplicationDelegate {
std::set<HTMLDocument*> documents(documents_);
for (HTMLDocument* doc : documents)
doc->Destroy();
+
+ std::set<HTMLDocumentOOPIF*> documents2(documents2_);
+ for (HTMLDocumentOOPIF* doc : documents2)
+ doc->Destroy();
}
// Callback from the quit closure. We key off this rather than
@@ -116,16 +130,29 @@ class HTMLDocumentApplicationDelegate : public mojo::ApplicationDelegate {
documents_.erase(document);
}
+ void OnHTMLDocumentDeleted2(HTMLDocumentOOPIF* document) {
+ DCHECK(documents2_.count(document) > 0);
+ documents2_.erase(document);
+ }
+
void OnResponseReceived(URLLoaderPtr loader,
mojo::ApplicationConnection* connection,
URLResponsePtr response) {
// HTMLDocument is destroyed when the hosting view is destroyed, or
// explicitly from our destructor.
- HTMLDocument* document = new HTMLDocument(
- &app_, connection, response.Pass(), setup_,
- base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted,
- base::Unretained(this)));
- documents_.insert(document);
+ if (EnableOOPIFs()) {
+ HTMLDocumentOOPIF* document = new HTMLDocumentOOPIF(
+ &app_, connection, response.Pass(), setup_,
+ base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted2,
+ base::Unretained(this)));
+ documents2_.insert(document);
+ } else {
+ HTMLDocument* document = new HTMLDocument(
+ &app_, connection, response.Pass(), setup_,
+ base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted,
+ base::Unretained(this)));
+ documents_.insert(document);
+ }
}
mojo::ApplicationImpl app_;
@@ -141,6 +168,10 @@ class HTMLDocumentApplicationDelegate : public mojo::ApplicationDelegate {
// HTMLDocument is deleted.
std::set<HTMLDocument*> documents_;
+ // As we create HTMLDocuments they are added here. They are removed when the
+ // HTMLDocument is deleted.
+ std::set<HTMLDocumentOOPIF*> documents2_;
+
DISALLOW_COPY_AND_ASSIGN(HTMLDocumentApplicationDelegate);
};