Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(589)

Unified Diff: content/browser/browser_plugin/browser_plugin_web_contents_observer.cc

Issue 9924026: Browser side implementation of browser plugin (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Updated message names Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/browser_plugin/browser_plugin_web_contents_observer.cc
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 0000000000000000000000000000000000000000..fb2b3746ed0841bdaa79f337b19da0470b3401ab
--- /dev/null
+++ b/content/browser/browser_plugin/browser_plugin_web_contents_observer.cc
@@ -0,0 +1,246 @@
+// 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/common/view_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"
+
+typedef std::map<content::WebContents*,
+ content::BrowserPluginWebContentsObserver*> Instances;
+
+namespace {
+base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
+namespace content {
+
+// static
+BrowserPluginWebContentsObserver*
+BrowserPluginWebContentsObserver::Get(
+ WebContents* web_contents) {
+ Instances::iterator it = g_instances.Get().find(web_contents);
+ if (it != g_instances.Get().end())
+ return it->second;
+ return new BrowserPluginWebContentsObserver(web_contents);
+}
+
+BrowserPluginWebContentsObserver::BrowserPluginWebContentsObserver(
+ WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ host_(NULL),
+ instance_id_(0) {
+ registrar_.Add(this,
+ NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
+ Source<RenderViewHost>(
+ web_contents->GetRenderViewHost()));
+ g_instances.Get()[web_contents] = this;
+}
+
+BrowserPluginWebContentsObserver::~BrowserPluginWebContentsObserver() {
+ g_instances.Get().erase(web_contents());
+}
+
+bool BrowserPluginWebContentsObserver::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BrowserPluginWebContentsObserver, message)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated,
+ OnRendererPluginChannelCreated)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToBrowserPlugin,
+ OnOpenChannelToBrowserPlugin)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_GuestReady, OnMsgGuestReady)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ResizeGuest, OnMsgResizeGuest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+ return handled;
+}
+
+void BrowserPluginWebContentsObserver::OnMsgGuestReady() {
jam 2012/04/04 00:54:45 nit: just name handlers OnFoo, no need for "OnMsgF
Fady Samuel 2012/04/04 16:45:40 Done.
+ // 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.
+ PpapiMsg_CreateChannel* msg =
+ new PpapiMsg_CreateChannel(host()->GetRenderProcessHost()->GetHandle(),
+ host()->GetRenderProcessHost()->GetID());
+ msg->set_routing_id(web_contents()->GetRenderViewHost()->GetRoutingID());
+ msg->set_unblock(true);
jam 2012/04/04 00:54:45 are you sure you want this (set the unblock flag)?
Fady Samuel 2012/04/04 16:45:40 I believe you're right, I don't want the set_unblo
jam 2012/04/04 21:07:19 ping. are you sure you need this? check the docume
Fady Samuel 2012/04/05 19:35:40 Removed.
+ // 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::OnMsgResizeGuest(
+ 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);
+ WebContents* guest_web_contents =
+ 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_web_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_web_contents->GetController().LoadURL(
+ url,
+ Referrer(),
+ PAGE_TRANSITION_HOME_PAGE,
+ std::string());
+
+ guest_render_view_host->GetView()->SetSize(size);
+ BrowserPluginWebContentsObserver* guest_observer = Get(guest_web_contents);
+ guest_observer->set_host(web_contents());
+ guest_observer->set_instance_id(instance_id);
+
+ AddGuest(guest_web_contents, frame_id);
+}
+
+// Called when a new plugin <--> renderer channel has been created.
jam 2012/04/04 00:54:45 nit: no need to document message handlers above th
Fady Samuel 2012/04/04 16:45:40 Done.
+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 browser loading placeholder that we're done.
+ // and that it can begin using the guest renderer.
+ host()->GetRenderProcessHost()->Send(
+ new ViewMsg_GuestReady_ACK(
+ host()->GetRenderViewHost()->GetRoutingID(),
+ instance_id(),
+ renderers_plugin_handle,
+ channel_handle));
+}
+
+void BrowserPluginWebContentsObserver::AddGuest(
+ WebContents* guest,
+ int64 frame_id) {
+ guests_[guest] = frame_id;
+}
+
+void BrowserPluginWebContentsObserver::RemoveGuest(
+ WebContents* guest) {
+ guests_.erase(guest);
+}
+
+void BrowserPluginWebContentsObserver::DestroyGuests() {
+ for (GuestMap::const_iterator it = guests_.begin();
+ it != guests_.end(); ++it) {
+ const WebContents* contents = it->first;
+ delete contents;
+ }
+ guests_.clear();
+}
+
+void BrowserPluginWebContentsObserver::DidCommitProvisionalLoadForFrame(
+ int64 frame_id,
+ bool is_main_frame,
+ const GURL& url,
+ PageTransition transition_type) {
+ GuestSet guests_to_delete;
+ for (GuestMap::const_iterator it = guests_.begin();
+ it != guests_.end(); ++it) {
+ WebContents* 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) {
+ WebContents* contents = it->first;
+ if (visible)
+ contents->ShowContents();
+ else
+ contents->HideContents();
+ }
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698