summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/browser_plugin/browser_plugin_web_contents_observer.cc229
-rw-r--r--content/browser/browser_plugin/browser_plugin_web_contents_observer.h94
-rw-r--r--content/browser/tab_contents/tab_contents.cc4
-rw-r--r--content/browser/tab_contents/tab_contents.h8
-rw-r--r--content/common/browser_plugin_messages.h72
-rw-r--r--content/common/content_message_generator.h1
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/content_common.gypi1
-rw-r--r--ipc/ipc_message_utils.h1
9 files changed, 412 insertions, 0 deletions
diff --git a/content/browser/browser_plugin/browser_plugin_web_contents_observer.cc b/content/browser/browser_plugin/browser_plugin_web_contents_observer.cc
new file mode 100644
index 0000000..0811a8d
--- /dev/null
+++ b/content/browser/browser_plugin/browser_plugin_web_contents_observer.cc
@@ -0,0 +1,229 @@
+// 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/browser/browser_plugin/browser_plugin_web_contents_observer.h"
+
+#include "base/lazy_instance.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/common/browser_plugin_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace content {
+
+BrowserPluginWebContentsObserver::BrowserPluginWebContentsObserver(
+ TabContents* tab_contents)
+ : WebContentsObserver(tab_contents),
+ host_(NULL),
+ instance_id_(0) {
+ registrar_.Add(this,
+ NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
+ Source<RenderViewHost>(
+ tab_contents->GetRenderViewHost()));
+}
+
+BrowserPluginWebContentsObserver::~BrowserPluginWebContentsObserver() {
+}
+
+bool BrowserPluginWebContentsObserver::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BrowserPluginWebContentsObserver, message)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ChannelCreated,
+ OnRendererPluginChannelCreated)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_OpenChannel,
+ OnOpenChannelToBrowserPlugin)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_GuestReady, OnGuestReady)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+ return handled;
+}
+
+void BrowserPluginWebContentsObserver::OnGuestReady() {
+ // We only care about handling this message on guests.
+ if (!host())
+ return;
+
+ // The renderer is now ready to receive ppapi messages.
+ // Let's tell it create a channel with the embedder/host.
+ BrowserPluginMsg_CreateChannel* msg =
+ new BrowserPluginMsg_CreateChannel(
+ host()->GetRenderProcessHost()->GetHandle(),
+ host()->GetRenderProcessHost()->GetID());
+ msg->set_routing_id(web_contents()->GetRenderViewHost()->GetRoutingID());
+ // TODO(fsamuel): If we aren't able to successfully send this message
+ // to the guest then that probably means it crashed. Is there anything
+ // we can do that's cleaner than failing a check?
+ CHECK(Send(msg));
+}
+
+void BrowserPluginWebContentsObserver::OnResizeGuest(
+ int width, int height) {
+ // Tell the RenderWidgetHostView to adjust its size.
+ web_contents()->GetRenderViewHost()->GetView()->SetSize(
+ gfx::Size(width, height));
+}
+
+void BrowserPluginWebContentsObserver::OnOpenChannelToBrowserPlugin(
+ int instance_id,
+ long long frame_id,
+ const std::string& src,
+ const gfx::Size& size) {
+ BrowserContext* browser_context =
+ web_contents()->GetRenderViewHost()->GetProcess()->GetBrowserContext();
+ DCHECK(browser_context);
+
+ GURL url(src);
+ SiteInstance* site_instance =
+ SiteInstance::CreateForURL(
+ browser_context, url);
+ TabContents* guest_tab_contents =
+ static_cast<TabContents*>(
+ WebContents::Create(
+ browser_context,
+ site_instance,
+ MSG_ROUTING_NONE,
+ NULL, // base tab contents
+ NULL // session storage namespace
+ ));
+ // TODO(fsamuel): Set the WebContentsDelegate here.
+ RenderViewHostImpl* guest_render_view_host =
+ static_cast<RenderViewHostImpl*>(
+ guest_tab_contents->GetRenderViewHost());
+
+ // We need to make sure that the RenderViewHost knows that it's
+ // hosting a guest RenderView so that it informs the RenderView
+ // on a ViewMsg_New. Guest RenderViews will avoid compositing
+ // until a guest-to-host channel has been initialized.
+ guest_render_view_host->set_guest(true);
+
+ guest_tab_contents->GetController().LoadURL(
+ url,
+ Referrer(),
+ PAGE_TRANSITION_HOME_PAGE,
+ std::string());
+
+ guest_render_view_host->GetView()->SetSize(size);
+ BrowserPluginWebContentsObserver* guest_observer =
+ guest_tab_contents->browser_plugin_web_contents_observer();
+ guest_observer->set_host(static_cast<TabContents*>(web_contents()));
+ guest_observer->set_instance_id(instance_id);
+
+ AddGuest(guest_tab_contents, frame_id);
+}
+
+void BrowserPluginWebContentsObserver::OnRendererPluginChannelCreated(
+ const IPC::ChannelHandle& channel_handle) {
+ DCHECK(host());
+ // Prepare the handle to send to the renderer.
+ base::ProcessHandle plugin_process =
+ web_contents()->GetRenderProcessHost()->GetHandle();
+#if defined(OS_WIN)
+ base::ProcessHandle renderer_process =
+ host()->GetRenderProcessHost()->GetHandle();
+ int renderer_id = host()->GetRenderProcessHost()->GetID();
+
+ base::ProcessHandle renderers_plugin_handle = NULL;
+ ::DuplicateHandle(::GetCurrentProcess(), plugin_process,
+ renderer_process, &renderers_plugin_handle,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+#elif defined(OS_POSIX)
+ // Don't need to duplicate anything on POSIX since it's just a PID.
+ base::ProcessHandle renderers_plugin_handle = plugin_process;
+#endif
+ // Tell the BrowserPLuginPlaceholder in the host that we're done
+ // and that it can begin using the guest renderer.
+ host()->GetRenderProcessHost()->Send(
+ new BrowserPluginMsg_GuestReady_ACK(
+ host()->GetRenderViewHost()->GetRoutingID(),
+ instance_id(),
+ renderers_plugin_handle,
+ channel_handle));
+}
+
+void BrowserPluginWebContentsObserver::AddGuest(
+ TabContents* guest,
+ int64 frame_id) {
+ guests_[guest] = frame_id;
+}
+
+void BrowserPluginWebContentsObserver::RemoveGuest(TabContents* guest) {
+ guests_.erase(guest);
+}
+
+void BrowserPluginWebContentsObserver::DestroyGuests() {
+ for (GuestMap::const_iterator it = guests_.begin();
+ it != guests_.end(); ++it) {
+ const TabContents* contents = it->first;
+ delete contents;
+ }
+ guests_.clear();
+}
+
+void BrowserPluginWebContentsObserver::DidCommitProvisionalLoadForFrame(
+ int64 frame_id,
+ bool is_main_frame,
+ const GURL& url,
+ PageTransition transition_type) {
+ typedef std::set<TabContents*> GuestSet;
+ GuestSet guests_to_delete;
+ for (GuestMap::const_iterator it = guests_.begin();
+ it != guests_.end(); ++it) {
+ TabContents* contents = it->first;
+ if (it->second == frame_id) {
+ guests_to_delete.insert(contents);
+ }
+ }
+ for (GuestSet::const_iterator it = guests_to_delete.begin();
+ it != guests_to_delete.end(); ++it) {
+ delete *it;
+ guests_.erase(*it);
+ }
+}
+
+void BrowserPluginWebContentsObserver::RenderViewDeleted(
+ RenderViewHost* render_view_host) {
+ DestroyGuests();
+}
+
+void BrowserPluginWebContentsObserver::RenderViewGone(
+ base::TerminationStatus status) {
+ DestroyGuests();
+}
+
+void BrowserPluginWebContentsObserver::WebContentsDestroyed(
+ WebContents* web_contents) {
+ DestroyGuests();
+}
+
+void BrowserPluginWebContentsObserver::Observe(
+ int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED);
+ bool visible = *Details<bool>(details).ptr();
+
+ // If the host is hidden we need to hide the guests as well.
+ for (GuestMap::const_iterator it = guests_.begin();
+ it != guests_.end(); ++it) {
+ TabContents* contents = it->first;
+ if (visible)
+ contents->ShowContents();
+ else
+ contents->HideContents();
+ }
+}
+
+} // namespace content
diff --git a/content/browser/browser_plugin/browser_plugin_web_contents_observer.h b/content/browser/browser_plugin/browser_plugin_web_contents_observer.h
new file mode 100644
index 0000000..fc7722f
--- /dev/null
+++ b/content/browser/browser_plugin/browser_plugin_web_contents_observer.h
@@ -0,0 +1,94 @@
+// 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_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_WEB_CONTENTS_OBSERVER_H__
+#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_WEB_CONTENTS_OBSERVER_H__
+#pragma once
+
+#include <map>
+
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "ui/gfx/size.h"
+
+class TabContents;
+
+namespace content {
+
+class BrowserPluginWebContentsObserver: public WebContentsObserver,
+ public NotificationObserver {
+ public:
+ BrowserPluginWebContentsObserver(TabContents* web_contents);
+
+ virtual ~BrowserPluginWebContentsObserver();
+
+ // A Host BrowserPluginWebContentsObserver keeps track of
+ // its guests so that if it navigates away, its associated RenderView
+ // crashes or it is hidden, it takes appropriate action on the guest.
+ void AddGuest(TabContents* guest, int64 frame_id);
+
+ void RemoveGuest(TabContents* guest);
+
+ TabContents* host() const { return host_; }
+
+ void set_host(TabContents* host) { host_ = host; }
+
+ int instance_id() const { return instance_id_; }
+
+ void set_instance_id(int instance_id) { instance_id_ = instance_id; }
+
+ // WebContentObserver implementation.
+
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ virtual void DidCommitProvisionalLoadForFrame(
+ int64 frame_id,
+ bool is_main_frame,
+ const GURL& url,
+ PageTransition transition_type) OVERRIDE;
+
+ virtual void RenderViewDeleted(
+ RenderViewHost* render_view_host) OVERRIDE;
+
+ virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
+
+ virtual void WebContentsDestroyed(WebContents* tab) OVERRIDE;
+
+ private:
+ typedef std::map<TabContents*, int64> GuestMap;
+
+ void OnOpenChannelToBrowserPlugin(int32 instance_id,
+ long long frame_id,
+ const std::string& src,
+ const gfx::Size& size);
+
+ void OnGuestReady();
+
+ void OnResizeGuest(int width, int height);
+
+ void OnRendererPluginChannelCreated(const IPC::ChannelHandle& handle);
+
+ void DestroyGuests();
+
+ // NotificationObserver method override.
+ virtual void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) OVERRIDE;
+
+ // A scoped container for notification registries.
+ NotificationRegistrar registrar_;
+
+ TabContents* host_;
+
+ // An identifier that uniquely identifies a browser plugin container
+ // within a host.
+ int instance_id_;
+
+ GuestMap guests_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_WEB_CONTENTS_OBSERVER_H_
diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc
index cd36641..bbaf198 100644
--- a/content/browser/tab_contents/tab_contents.cc
+++ b/content/browser/tab_contents/tab_contents.cc
@@ -14,6 +14,7 @@
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
+#include "content/browser/browser_plugin/browser_plugin_web_contents_observer.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/debugger/devtools_manager_impl.h"
#include "content/browser/download/download_stats.h"
@@ -307,6 +308,9 @@ TabContents::TabContents(content::BrowserContext* browser_context,
java_bridge_dispatcher_host_manager_.reset(
new JavaBridgeDispatcherHostManager(this));
#endif
+
+ browser_plugin_web_contents_observer_.reset(
+ new content::BrowserPluginWebContentsObserver(this));
}
TabContents::~TabContents() {
diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h
index 2fe0ec3..7110bf7 100644
--- a/content/browser/tab_contents/tab_contents.h
+++ b/content/browser/tab_contents/tab_contents.h
@@ -14,6 +14,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/property_bag.h"
+#include "content/browser/browser_plugin/browser_plugin_web_contents_observer.h"
#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
#include "content/browser/tab_contents/navigation_controller_impl.h"
#include "content/browser/tab_contents/render_view_host_manager.h"
@@ -124,6 +125,11 @@ class CONTENT_EXPORT TabContents
return java_bridge_dispatcher_host_manager_.get();
}
+ content::BrowserPluginWebContentsObserver*
+ browser_plugin_web_contents_observer() const {
+ return browser_plugin_web_contents_observer_.get();
+ }
+
// Like GetController from WebContents, but returns the concrete object.
NavigationControllerImpl& GetControllerImpl();
@@ -560,6 +566,8 @@ class CONTENT_EXPORT TabContents
scoped_ptr<JavaBridgeDispatcherHostManager>
java_bridge_dispatcher_host_manager_;
+ scoped_ptr<content::BrowserPluginWebContentsObserver>
+ browser_plugin_web_contents_observer_;
// SavePackage, lazily created.
scoped_refptr<SavePackage> save_package_;
diff --git a/content/common/browser_plugin_messages.h b/content/common/browser_plugin_messages.h
new file mode 100644
index 0000000..db40c45
--- /dev/null
+++ b/content/common/browser_plugin_messages.h
@@ -0,0 +1,72 @@
+// 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.
+
+// Multiply-included message header, no traditional include guard.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/process.h"
+#include "content/common/content_export.h"
+#include "content/public/common/common_param_traits.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+#include "ui/gfx/size.h"
+
+#define IPC_MESSAGE_START BrowserPluginMsgStart
+
+// Browser plugin messages
+
+// -----------------------------------------------------------------------------
+// These messages are from the host renderer to the browser process
+
+// A renderer sends this to the browser process when it wants to
+// create a browser plugin. The browser will create a guest renderer process
+// if necessary.
+IPC_MESSAGE_ROUTED4(BrowserPluginHostMsg_OpenChannel,
+ int /* plugin instance id*/,
+ long long /* frame id */,
+ std::string /* src */,
+ gfx::Size /* size */)
+
+// -----------------------------------------------------------------------------
+// These messages are from the browser process to the guest renderer.
+
+// Creates a channel to talk to a renderer. The guest renderer will respond
+// with BrowserPluginHostMsg_ChannelCreated.
+IPC_MESSAGE_CONTROL2(BrowserPluginMsg_CreateChannel,
+ base::ProcessHandle /* host_renderer_process_handle */,
+ int /* host_renderer_id */)
+
+// -----------------------------------------------------------------------------
+// These messages are from the guest renderer to the browser process
+
+// Reply to BrowserPluginMsg_CreateChannel. The handle will be NULL if the
+// channel could not be established. This could be because the IPC could not be
+// created for some weird reason, but more likely that the renderer failed to
+// initialize properly.
+IPC_MESSAGE_CONTROL1(BrowserPluginHostMsg_ChannelCreated,
+ IPC::ChannelHandle /* handle */)
+
+// Indicates the guest renderer is ready in response to a ViewMsg_New
+IPC_MESSAGE_ROUTED0(BrowserPluginHostMsg_GuestReady)
+
+// A host renderer sends this message to the browser when it wants
+// to resize a guest plugin container so that the guest is relaid out
+// according to the new size.
+IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ResizeGuest,
+ int32, /* width */
+ int32 /* height */)
+
+// -----------------------------------------------------------------------------
+// These messages are from the browser process to the host renderer.
+
+// A guest instance is ready to be placed.
+IPC_MESSAGE_ROUTED3(BrowserPluginMsg_GuestReady_ACK,
+ int /* instance id */,
+ base::ProcessHandle /* plugin_process_handle */,
+ IPC::ChannelHandle /* handle to channel */)
+
+
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index 9ef7371..82e650e 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -8,6 +8,7 @@
#include "content/common/accessibility_messages.h"
#include "content/common/appcache_messages.h"
+#include "content/common/browser_plugin_messages.h"
#include "content/common/clipboard_messages.h"
#include "content/common/database_messages.h"
#include "content/common/desktop_notification_messages.h"
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 21b21d7..712d888 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -188,6 +188,8 @@
'browser/browser_main_loop.cc',
'browser/browser_main_loop.h',
'browser/browser_main_runner.cc',
+ 'browser/browser_plugin/browser_plugin_web_contents_observer.cc',
+ 'browser/browser_plugin/browser_plugin_web_contents_observer.h',
'browser/browser_process_sub_thread.cc',
'browser/browser_process_sub_thread.h',
'browser/browser_thread_impl.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 25f42b7..117339a 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -96,6 +96,7 @@
'common/appcache/appcache_dispatcher.cc',
'common/appcache/appcache_dispatcher.h',
'common/appcache_messages.h',
+ 'common/browser_plugin_messages.h',
'common/child_process.cc',
'common/child_process.h',
'common/child_process_host_impl.cc',
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index dc4a4be..8772b67 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -101,6 +101,7 @@ enum IPCMessageStart {
AccessibilityMsgStart,
PrerenderMsgStart,
ChromotingMsgStart,
+ BrowserPluginMsgStart,
LastIPCMsgStart // Must come last.
};