summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorfsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-14 06:42:53 +0000
committerfsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-14 06:42:53 +0000
commit0361b94c5041bd426dfaabce29d780129650a80e (patch)
tree35595d1ab73563498603fa5f248e568f126343bc /content
parentb67eb31f6b3a80d6f3e635608d4574e31c475d6e (diff)
downloadchromium_src-0361b94c5041bd426dfaabce29d780129650a80e.zip
chromium_src-0361b94c5041bd426dfaabce29d780129650a80e.tar.gz
chromium_src-0361b94c5041bd426dfaabce29d780129650a80e.tar.bz2
Implement BrowserPluginPlaceholder.
A browser plugin is a plugin container that hosts an out-of-process RenderView (guest). Loading up a new process, creating a new RenderView, navigating to a given URL, and establishing a guest-to-host channel can take hundreds of milliseconds. Furthermore, a RenderView's associated browser-side WebContents, RenderViewHost, and SiteInstance must be created and accessed on the UI thread thread on the browser. Thus, we must avoid blocking the host RenderView as well to avoid introducing the potential for a deadlock. To address the two issues above, we use a BrowserPluginPlaceholder (currently an empty WebViewPlugin wrapper) to take place of the guest renderer until the guest renderer is ready. BUG=117894 TEST=manually Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=126534 Review URL: http://codereview.chromium.org/9668031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126598 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc1
-rw-r--r--content/content_renderer.gypi4
-rw-r--r--content/public/common/content_switches.cc3
-rw-r--r--content/public/common/content_switches.h1
-rw-r--r--content/renderer/browser_plugin/browser_plugin_constants.cc10
-rw-r--r--content/renderer/browser_plugin/browser_plugin_constants.h13
-rw-r--r--content/renderer/browser_plugin/browser_plugin_placeholder.cc143
-rw-r--r--content/renderer/browser_plugin/browser_plugin_placeholder.h89
-rw-r--r--content/renderer/render_view_impl.cc11
9 files changed, 275 insertions, 0 deletions
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index b4bd350..869bdf0 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -678,6 +678,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableWebSockets,
switches::kDomAutomationController,
switches::kEnableAccessibilityLogging,
+ switches::kEnableBrowserPlugin,
switches::kEnableDCHECK,
switches::kEnableFixedLayout,
switches::kEnableGamepad,
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index ec87f80..ca7fc6c 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -143,6 +143,10 @@
'renderer/pepper/pepper_proxy_channel_delegate_impl.h',
'renderer/plugin_channel_host.cc',
'renderer/plugin_channel_host.h',
+ 'renderer/browser_plugin/browser_plugin_constants.cc',
+ 'renderer/browser_plugin/browser_plugin_constants.h',
+ 'renderer/browser_plugin/browser_plugin_placeholder.cc',
+ 'renderer/browser_plugin/browser_plugin_placeholder.h',
'renderer/render_process.h',
'renderer/render_process_impl.cc',
'renderer/render_process_impl.h',
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 865f768..0c2ac2a 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -223,6 +223,9 @@ const char kEnableAccessibility[] = "enable-accessibility";
// Turns on extremely verbose logging of accessibility events.
const char kEnableAccessibilityLogging[] = "enable-accessibility-logging";
+// Turns on the browser plugin.
+const char kEnableBrowserPlugin[] = "enable-browser-plugin";
+
// Enables the creation of compositing layers for fixed position elements.
const char kEnableCompositingForFixedPosition[] =
"enable-fixed-position-compositing";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 97dbeb3..668a326 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -78,6 +78,7 @@ CONTENT_EXPORT extern const char kEnableAcceleratedPainting[];
CONTENT_EXPORT extern const char kEnableAcceleratedFilters[];
extern const char kEnableAccessibility[];
extern const char kEnableAccessibilityLogging[];
+extern const char kEnableBrowserPlugin[];
CONTENT_EXPORT extern const char kEnableCompositingForFixedPosition[];
extern const char kEnableCssRegions[];
CONTENT_EXPORT extern const char kEnableDeferred2dCanvas[];
diff --git a/content/renderer/browser_plugin/browser_plugin_constants.cc b/content/renderer/browser_plugin/browser_plugin_constants.cc
new file mode 100644
index 0000000..9e62b9e
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_constants.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_constants.h"
+
+const char kBrowserPluginName[] = "Browser Plugin";
+const char kBrowserPluginMimeType[] = "application/browser-plugin";
+const char kBrowserPluginPath[] = "internal/browser-plugin";
+const char kBrowserPluginDescription[] = "Out-of-Process Browser Plugin";
diff --git a/content/renderer/browser_plugin/browser_plugin_constants.h b/content/renderer/browser_plugin/browser_plugin_constants.h
new file mode 100644
index 0000000..446bd0c
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_constants.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_CONSTANTS_H_
+#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_CONSTANTS_H_
+
+extern const char kBrowserPluginName[];
+extern const char kBrowserPluginMimeType[];
+extern const char kBrowserPluginPath[];
+extern const char kBrowserPluginDescription[];
+
+#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_CONSTANTS_H_
diff --git a/content/renderer/browser_plugin/browser_plugin_placeholder.cc b/content/renderer/browser_plugin/browser_plugin_placeholder.cc
new file mode 100644
index 0000000..21ac8ee
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_placeholder.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_placeholder.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/id_map.h"
+#include "base/lazy_instance.h"
+#include "base/process.h"
+#include "base/string_number_conversions.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "content/common/view_messages.h"
+#include "content/public/renderer/render_view.h"
+#include "ipc/ipc_channel_handle.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPlugin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
+#include "webkit/plugins/webview_plugin.h"
+
+static base::StaticAtomicSequenceNumber g_next_id;
+
+// The global list of all Browser Plugin Placeholders within a process.
+base::LazyInstance<IDMap<BrowserPluginPlaceholder> >::Leaky
+ g_all_placeholders = LAZY_INSTANCE_INITIALIZER;
+
+using webkit::WebViewPlugin;
+using WebKit::WebPlugin;
+using WebKit::WebPluginContainer;
+
+const char* const kPluginPlaceholderDataURL =
+ "about:blank";
+
+// static
+webkit::WebViewPlugin* BrowserPluginPlaceholder::Create(
+ content::RenderView* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params) {
+ // TODO(fsamuel): Need a better loading screen at some point. Maybe this can
+ // be a part of the <browser> API?
+ // |browser_plugin| will destroy itself when its WebViewPlugin is going away.
+ BrowserPluginPlaceholder* browser_plugin = new BrowserPluginPlaceholder(
+ render_view, frame, params, "");
+ return browser_plugin->plugin();
+}
+
+// static
+BrowserPluginPlaceholder* BrowserPluginPlaceholder::FromID(int id) {
+ return g_all_placeholders.Get().Lookup(id);
+}
+
+BrowserPluginPlaceholder::BrowserPluginPlaceholder(
+ content::RenderView* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params,
+ const std::string& html_data)
+ : render_view_(render_view),
+ plugin_params_(params),
+ plugin_(webkit::WebViewPlugin::Create(
+ this, render_view->GetWebkitPreferences(), html_data,
+ GURL(kPluginPlaceholderDataURL))) {
+ id_ = g_next_id.GetNext();
+ RegisterPlaceholder(GetID(), this);
+
+ // By default we navigate to google.com
+ GetPluginParameters(0, 0, "http://www.google.com/");
+
+ // TODO(fsamuel): Request a browser plugin instance from the
+ // browser process.
+}
+
+BrowserPluginPlaceholder::~BrowserPluginPlaceholder() {
+ UnregisterPlaceholder(GetID());
+}
+
+void BrowserPluginPlaceholder::RegisterPlaceholder(
+ int id,
+ BrowserPluginPlaceholder* placeholder) {
+ g_all_placeholders.Get().AddWithID(placeholder, id);
+}
+
+void BrowserPluginPlaceholder::UnregisterPlaceholder(int id) {
+ if (g_all_placeholders.Get().Lookup(id))
+ g_all_placeholders.Get().Remove(id);
+}
+
+const WebKit::WebPluginParams& BrowserPluginPlaceholder::plugin_params() const {
+ return plugin_params_;
+}
+
+void BrowserPluginPlaceholder::GetPluginParameters(
+ int default_width, int default_height,
+ const std::string& default_src) {
+ int width = default_width;
+ int height = default_height;
+
+ // Get the plugin parameters from the attributes vector
+ for (unsigned i = 0; i < plugin_params_.attributeNames.size(); ++i) {
+ std::string attributeName = plugin_params_.attributeNames[i].utf8();
+ if (LowerCaseEqualsASCII(attributeName, "width")) {
+ std::string attributeValue = plugin_params_.attributeValues[i].utf8();
+ CHECK(base::StringToInt(attributeValue, &width));
+ } else if (LowerCaseEqualsASCII(attributeName, "height")) {
+ std::string attributeValue = plugin_params_.attributeValues[i].utf8();
+ CHECK(base::StringToInt(attributeValue, &height));
+ } else if (LowerCaseEqualsASCII(attributeName, "src")) {
+ src_ = plugin_params_.attributeValues[i].utf8();
+ }
+ }
+ // If we didn't find the attributes set or they're not sensible,
+ // we reset our attributes to the default.
+ if (src_.empty())
+ src_ = default_src;
+
+ size_.SetSize(width, height);
+}
+
+void BrowserPluginPlaceholder::GuestReady(
+ base::ProcessHandle process_handle,
+ const IPC::ChannelHandle& channel_handle) {
+ // TODO(fsamuel): Once the guest renderer is ready,
+ // it will inform the host renderer and the BrowserPluginPlaceholder
+ // can swap itself out with the guest.
+ NOTIMPLEMENTED();
+}
+
+void BrowserPluginPlaceholder::LoadGuest(WebKit::WebPlugin* new_plugin) {
+ WebKit::WebPluginContainer* container = plugin_->container();
+ if (!new_plugin || !new_plugin->initialize(container))
+ return;
+ plugin_->RestoreTitleText();
+ container->setPlugin(new_plugin);
+ container->invalidate();
+ container->reportGeometry();
+ plugin_->ReplayReceivedData(new_plugin);
+ plugin_->destroy();
+}
+
+void BrowserPluginPlaceholder::WillDestroyPlugin() {
+ delete this;
+}
diff --git a/content/renderer/browser_plugin/browser_plugin_placeholder.h b/content/renderer/browser_plugin/browser_plugin_placeholder.h
new file mode 100644
index 0000000..b7c229d
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_placeholder.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_PLACEHOLDER_H_
+#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_PLACEHOLDER_H_
+#pragma once
+
+#include "base/process.h"
+#include "ipc/ipc_channel_handle.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
+#include "ui/gfx/size.h"
+#include "webkit/plugins/webview_plugin.h"
+
+namespace content {
+class RenderView;
+}
+
+namespace WebKit {
+class WebPlugin;
+}
+
+// A browser plugin is a plugin container that hosts an out-of-process "guest"
+// RenderView. Loading up a new process, creating a new RenderView, navigating
+// to a given URL, and establishing a guest-to-host channel can take hundreds
+// of milliseconds. Furthermore, a RenderView's associated browser-side
+// WebContents, RenderViewHost, and SiteInstance must be created and accessed on
+// the UI thread of the browser process.
+//
+// To avoid blocking the host RenderView and to avoid introducing the potential
+// for deadlock, the BrowserPluginPlaceholder takes place of the guest
+// RenderView until the guest has established a connection with its host
+// RenderView. This permits loading the guest to happen asynchronously, while
+// the host RenderView is permitted to continue to receive and process events.
+class BrowserPluginPlaceholder: public webkit::WebViewPlugin::Delegate {
+ public:
+ // Creates a new WebViewPlugin with a BrowserPluginPlaceholder as a delegate.
+ static webkit::WebViewPlugin* Create(
+ content::RenderView* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params);
+
+ static BrowserPluginPlaceholder* FromID(int id);
+
+ void RegisterPlaceholder(int id, BrowserPluginPlaceholder* placeholder);
+ void UnregisterPlaceholder(int id);
+
+ int GetID() { return id_; }
+
+ webkit::WebViewPlugin* plugin() { return plugin_; }
+
+ const WebKit::WebPluginParams& plugin_params() const;
+
+ void GuestReady(base::ProcessHandle process_handle,
+ const IPC::ChannelHandle& channel_handle);
+
+ content::RenderView* render_view() { return render_view_; }
+
+ private:
+ BrowserPluginPlaceholder(content::RenderView* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params,
+ const std::string& html_data);
+ virtual ~BrowserPluginPlaceholder();
+
+ // Grabs the width, height, and source URL of the browser plugin
+ // from the element's attributes. If not found, it uses the defaults
+ // specified here as parameters.
+ void GetPluginParameters(int default_width, int default_height,
+ const std::string& default_src);
+ // Replace this placeholder with the real browser plugin.
+ void LoadGuest(WebKit::WebPlugin* new_plugin);
+
+ virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE { }
+ virtual void WillDestroyPlugin() OVERRIDE;
+ virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE { }
+
+ content::RenderView* render_view_;
+ WebKit::WebPluginParams plugin_params_;
+ webkit::WebViewPlugin* plugin_;
+ int id_;
+ gfx::Size size_;
+ std::string src_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserPluginPlaceholder);
+};
+
+#endif // CONTNET_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_PLACEHOLDER_H_
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index a1097c3..9db8271 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -73,6 +73,8 @@
#include "content/renderer/notification_provider.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "content/renderer/plugin_channel_host.h"
+#include "content/renderer/browser_plugin/browser_plugin_constants.h"
+#include "content/renderer/browser_plugin/browser_plugin_placeholder.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
@@ -2066,6 +2068,15 @@ bool RenderViewImpl::isPointerLocked() {
WebPlugin* RenderViewImpl::createPlugin(WebFrame* frame,
const WebPluginParams& params) {
+ // The browser plugin is a special kind of pepper plugin
+ // that loads asynchronously. We first create a placeholder here.
+ // When a guest is ready to be displayed, we swap out the placeholder
+ // with the guest.
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kEnableBrowserPlugin) &&
+ UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType)
+ return BrowserPluginPlaceholder::Create(this, frame, params);
+
WebPlugin* plugin = NULL;
if (content::GetContentClient()->renderer()->OverrideCreatePlugin(
this, frame, params, &plugin)) {