diff options
author | fsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-06 03:41:14 +0000 |
---|---|---|
committer | fsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-06 03:41:14 +0000 |
commit | 8eb0456079b454de26ebb823cdd5c93c44fa7430 (patch) | |
tree | 81cc73cc673837512599697bc38bc9aa75a4327b | |
parent | 953951d405cbac9a99355f2b99cb78ea5ad6a1f6 (diff) | |
download | chromium_src-8eb0456079b454de26ebb823cdd5c93c44fa7430.zip chromium_src-8eb0456079b454de26ebb823cdd5c93c44fa7430.tar.gz chromium_src-8eb0456079b454de26ebb823cdd5c93c44fa7430.tar.bz2 |
Browser Plugin: Implement BrowserPluginGuestManager
This patch centralizes instance ID allocation and routing to a per-profile object called BrowserPluginGuestManager.
This patch minimizes BrowserPluginEmbedder's responsibilities without entirely removing it.
BrowserPluginEmbedder lives for the lifetime of an embedder WebContents. It handles IPC messages that are not directed at any particular guest process, currently those are:
BrowserPluginHostMsg_AllocateInstanceID
BrowserPluginHostMsg_CreateGuest,
BrowserPluginHostMsg_PluginAtPositionResponse
These message handlers were kept in BrowserPluginEmbedder because they either operate on the embedder (as with PluginAtPosition), or they need to reply back to the correct BrowserPluginManager. This requires an understanding of the process ID and routing ID of the origin of the message. This information does not seem particularly appropriate in BrowserPluginGuestManager because that object spans multiple embedders and potentially multiple processes (outside of Chrome Apps).
BUG=174673, 140316
Test=BrowserPluginHostTest.*
Review URL: https://chromiumcodereview.appspot.com/12253046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186338 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 759 insertions, 486 deletions
diff --git a/content/browser/browser_plugin/browser_plugin_embedder.cc b/content/browser/browser_plugin/browser_plugin_embedder.cc index 6fc43f67..ddabe7e 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder.cc +++ b/content/browser/browser_plugin/browser_plugin_embedder.cc @@ -4,14 +4,14 @@ #include "content/browser/browser_plugin/browser_plugin_embedder.h" -#include "base/command_line.h" -#include "base/stl_util.h" #include "content/browser/browser_plugin/browser_plugin_guest.h" +#include "content/browser/browser_plugin/browser_plugin_guest_manager.h" #include "content/browser/browser_plugin/browser_plugin_host_factory.h" -#include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/browser_plugin/browser_plugin_constants.h" #include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/common/gpu/gpu_messages.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/user_metrics.h" #include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" @@ -23,13 +23,9 @@ namespace content { // static BrowserPluginHostFactory* BrowserPluginEmbedder::factory_ = NULL; -BrowserPluginEmbedder::BrowserPluginEmbedder( - WebContentsImpl* web_contents, - RenderViewHost* render_view_host) +BrowserPluginEmbedder::BrowserPluginEmbedder(WebContentsImpl* web_contents) : WebContentsObserver(web_contents), - render_view_host_(render_view_host), - next_get_render_view_request_id_(0), - next_instance_id_(0) { + next_get_render_view_request_id_(0) { } BrowserPluginEmbedder::~BrowserPluginEmbedder() { @@ -38,108 +34,10 @@ BrowserPluginEmbedder::~BrowserPluginEmbedder() { // static BrowserPluginEmbedder* BrowserPluginEmbedder::Create( - WebContentsImpl* web_contents, - content::RenderViewHost* render_view_host) { - if (factory_) { - return factory_->CreateBrowserPluginEmbedder(web_contents, - render_view_host); - } - return new BrowserPluginEmbedder(web_contents, render_view_host); -} - -void BrowserPluginEmbedder::CreateGuest( - int instance_id, - int routing_id, - BrowserPluginGuest* guest_opener, - const BrowserPluginHostMsg_CreateGuest_Params& params) { - SiteInstance* guest_site_instance = NULL; - BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); - CHECK(!guest); - - // Validate that the partition id coming from the renderer is valid UTF-8, - // since we depend on this in other parts of the code, such as FilePath - // creation. If the validation fails, treat it as a bad message and kill the - // renderer process. - if (!IsStringUTF8(params.storage_partition_id)) { - content::RecordAction(UserMetricsAction("BadMessageTerminate_BPE")); - base::KillProcess(render_view_host_->GetProcess()->GetHandle(), - content::RESULT_CODE_KILLED_BAD_MESSAGE, false); - return; - } - - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kSitePerProcess)) { - // When --site-per-process is specified, the behavior of BrowserPlugin - // as <webview> is broken and we use it for rendering out-of-process - // iframes instead. We use the src URL sent by the renderer to find the - // right process in which to place this instance. - // Note: Since BrowserPlugin doesn't support cross-process navigation, - // the instance will stay in the initially assigned process, regardless - // of the site it is navigated to. - // TODO(nasko): Fix this, and such that cross-process navigations are - // supported. - guest_site_instance = - web_contents()->GetSiteInstance()->GetRelatedSiteInstance( - GURL(params.src)); - } else { - const std::string& host = - render_view_host_->GetSiteInstance()->GetSiteURL().host(); - std::string url_encoded_partition = net::EscapeQueryParamValue( - params.storage_partition_id, false); - - if (guest_opener) { - guest_site_instance = guest_opener->GetWebContents()->GetSiteInstance(); - } else { - // The SiteInstance of a given webview tag is based on the fact that it's - // a guest process in addition to which platform application the tag - // belongs to and what storage partition is in use, rather than the URL - // that the tag is being navigated to. - GURL guest_site( - base::StringPrintf("%s://%s/%s?%s", chrome::kGuestScheme, - host.c_str(), - params.persist_storage ? "persist" : "", - url_encoded_partition.c_str())); - - // If we already have a webview tag in the same app using the same storage - // partition, we should use the same SiteInstance so the existing tag and - // the new tag can script each other. - for (ContainerInstanceMap::const_iterator it = - guest_web_contents_by_instance_id_.begin(); - it != guest_web_contents_by_instance_id_.end(); ++it) { - if (it->second->GetSiteInstance()->GetSiteURL() == guest_site) { - guest_site_instance = it->second->GetSiteInstance(); - break; - } - } - if (!guest_site_instance) { - // Create the SiteInstance in a new BrowsingInstance, which will ensure - // that webview tags are also not allowed to send messages across - // different partitions. - guest_site_instance = SiteInstance::CreateForURL( - web_contents()->GetBrowserContext(), guest_site); - } - } - } - - WebContentsImpl* opener_web_contents = static_cast<WebContentsImpl*>( - guest_opener ? guest_opener->GetWebContents() : NULL); - WebContentsImpl::CreateGuest( - web_contents()->GetBrowserContext(), - guest_site_instance, - routing_id, - static_cast<WebContentsImpl*>(web_contents()), - opener_web_contents, - instance_id, - params); -} - -BrowserPluginGuest* BrowserPluginEmbedder::GetGuestByInstanceID( - int instance_id) const { - ContainerInstanceMap::const_iterator it = - guest_web_contents_by_instance_id_.find(instance_id); - if (it != guest_web_contents_by_instance_id_.end()) - return static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest(); - return NULL; + WebContentsImpl* web_contents) { + if (factory_) + return factory_->CreateBrowserPluginEmbedder(web_contents); + return new BrowserPluginEmbedder(web_contents); } void BrowserPluginEmbedder::GetRenderViewHostAtPosition( @@ -147,33 +45,18 @@ void BrowserPluginEmbedder::GetRenderViewHostAtPosition( // Store the callback so we can call it later when we have the response. pending_get_render_view_callbacks_.insert( std::make_pair(next_get_render_view_request_id_, callback)); - render_view_host_->Send( - new BrowserPluginMsg_PluginAtPositionRequest( - render_view_host_->GetRoutingID(), - next_get_render_view_request_id_, - gfx::Point(x, y))); + Send(new BrowserPluginMsg_PluginAtPositionRequest( + routing_id(), + next_get_render_view_request_id_, + gfx::Point(x, y))); ++next_get_render_view_request_id_; } -void BrowserPluginEmbedder::RenderViewDeleted( - RenderViewHost* render_view_host) { -} - void BrowserPluginEmbedder::RenderViewGone(base::TerminationStatus status) { CleanUp(); } bool BrowserPluginEmbedder::OnMessageReceived(const IPC::Message& message) { - if (ShouldForwardToBrowserPluginGuest(message)) { - int instance_id = 0; - // All allowed messages must have instance_id as their first parameter. - PickleIterator iter(message); - bool success = iter.ReadInt(&instance_id); - DCHECK(success); - BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); - if (guest && guest->OnMessageReceivedFromEmbedder(message)) - return true; - } bool handled = true; IPC_BEGIN_MESSAGE_MAP(BrowserPluginEmbedder, message) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_AllocateInstanceID, @@ -182,26 +65,11 @@ bool BrowserPluginEmbedder::OnMessageReceived(const IPC::Message& message) { OnCreateGuest) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginAtPositionResponse, OnPluginAtPositionResponse) - IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK, - OnUnhandledSwapBuffersACK) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } -void BrowserPluginEmbedder::AddGuest(int instance_id, - WebContents* guest_web_contents) { - DCHECK(guest_web_contents_by_instance_id_.find(instance_id) == - guest_web_contents_by_instance_id_.end()); - guest_web_contents_by_instance_id_[instance_id] = guest_web_contents; -} - -void BrowserPluginEmbedder::RemoveGuest(int instance_id) { - DCHECK(guest_web_contents_by_instance_id_.find(instance_id) != - guest_web_contents_by_instance_id_.end()); - guest_web_contents_by_instance_id_.erase(instance_id); -} - void BrowserPluginEmbedder::CleanUp() { // CleanUp gets called when BrowserPluginEmbedder's WebContents goes away // or the associated RenderViewHost is destroyed or swapped out. Therefore we @@ -209,45 +77,32 @@ void BrowserPluginEmbedder::CleanUp() { pending_get_render_view_callbacks_.clear(); } -// static -bool BrowserPluginEmbedder::ShouldForwardToBrowserPluginGuest( - const IPC::Message& message) { - switch (message.type()) { - case BrowserPluginHostMsg_BuffersSwappedACK::ID: - case BrowserPluginHostMsg_DragStatusUpdate::ID: - case BrowserPluginHostMsg_Go::ID: - case BrowserPluginHostMsg_HandleInputEvent::ID: - case BrowserPluginHostMsg_NavigateGuest::ID: - case BrowserPluginHostMsg_PluginDestroyed::ID: - case BrowserPluginHostMsg_Reload::ID: - case BrowserPluginHostMsg_ResizeGuest::ID: - case BrowserPluginHostMsg_RespondPermission::ID: - case BrowserPluginHostMsg_SetAutoSize::ID: - case BrowserPluginHostMsg_SetFocus::ID: - case BrowserPluginHostMsg_SetName::ID: - case BrowserPluginHostMsg_SetVisibility::ID: - case BrowserPluginHostMsg_Stop::ID: - case BrowserPluginHostMsg_TerminateGuest::ID: - case BrowserPluginHostMsg_UpdateRect_ACK::ID: - case BrowserPluginHostMsg_LockMouse_ACK::ID: - case BrowserPluginHostMsg_UnlockMouse_ACK::ID: - return true; - default: - break; +BrowserPluginGuestManager* + BrowserPluginEmbedder::GetBrowserPluginGuestManager() { + BrowserPluginGuestManager* guest_manager = static_cast<WebContentsImpl*>( + web_contents())->GetBrowserPluginGuestManager(); + if (!guest_manager) { + guest_manager = BrowserPluginGuestManager::Create(); + web_contents()->GetBrowserContext()->SetUserData( + browser_plugin::kBrowserPluginGuestManagerKeyName, guest_manager); } - return false; + return guest_manager; } void BrowserPluginEmbedder::OnAllocateInstanceID(int request_id) { - int instance_id = ++next_instance_id_; - render_view_host_->Send(new BrowserPluginMsg_AllocateInstanceID_ACK( - render_view_host_->GetRoutingID(), request_id, instance_id)); + int instance_id = GetBrowserPluginGuestManager()->get_next_instance_id(); + Send(new BrowserPluginMsg_AllocateInstanceID_ACK( + routing_id(), request_id, instance_id)); } void BrowserPluginEmbedder::OnCreateGuest( int instance_id, const BrowserPluginHostMsg_CreateGuest_Params& params) { - CreateGuest(instance_id, MSG_ROUTING_NONE, NULL, params); + BrowserPluginGuest* guest = GetBrowserPluginGuestManager()->CreateGuest( + web_contents()->GetSiteInstance(), + instance_id, MSG_ROUTING_NONE, NULL, params); + if (guest) + guest->Initialize(static_cast<WebContentsImpl*>(web_contents()), params); } void BrowserPluginEmbedder::OnPluginAtPositionResponse( @@ -258,28 +113,16 @@ void BrowserPluginEmbedder::OnPluginAtPositionResponse( return; RenderViewHost* render_view_host; - BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id); + BrowserPluginGuest* guest = + GetBrowserPluginGuestManager()->GetGuestByInstanceID( + instance_id, web_contents()->GetRenderProcessHost()->GetID()); if (guest) render_view_host = guest->GetWebContents()->GetRenderViewHost(); else // No plugin, use embedder's RenderViewHost. - render_view_host = render_view_host_; + render_view_host = web_contents()->GetRenderViewHost(); callback_iter->second.Run(render_view_host, position.x(), position.y()); pending_get_render_view_callbacks_.erase(callback_iter); } -// We only get here during teardown if we have one last buffer pending, -// otherwise the ACK is handled by the guest. -void BrowserPluginEmbedder::OnUnhandledSwapBuffersACK( - int instance_id, - int route_id, - int gpu_host_id, - const std::string& mailbox_name, - uint32 sync_point) { - BrowserPluginGuest::AcknowledgeBufferPresent(route_id, - gpu_host_id, - mailbox_name, - sync_point); -} - } // namespace content diff --git a/content/browser/browser_plugin/browser_plugin_embedder.h b/content/browser/browser_plugin/browser_plugin_embedder.h index 5703fd9..42ce60d 100644 --- a/content/browser/browser_plugin/browser_plugin_embedder.h +++ b/content/browser/browser_plugin/browser_plugin_embedder.h @@ -2,20 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// A BrowserPluginEmbedder has a list of guests it manages. -// In the beginning when a renderer sees one or more guests (BrowserPlugin -// instance(s)) and there is a request to navigate to them, the WebContents for -// that renderer creates a BrowserPluginEmbedder for itself. The -// BrowserPluginEmbedder, in turn, manages a set of BrowserPluginGuests -- one -// BrowserPluginGuest for each guest in the embedding WebContents. Note that -// each of these BrowserPluginGuest objects has its own WebContents. -// BrowserPluginEmbedder routes any messages directed to a guest from the -// renderer (BrowserPlugin) to the appropriate guest (identified by the guest's -// |instance_id|). -// -// BrowserPluginEmbedder is responsible for cleaning up the guests when the -// embedder frame navigates away to a different page or deletes the guests from -// the existing page. +// A BrowserPluginEmbedder handles messages coming from a BrowserPlugin's +// embedder that are not directed at any particular existing guest process. +// In the beginning, when a BrowserPlugin instance in the embedder renderer +// process requests an initial navigation, the WebContents for that renderer +// renderer creates a BrowserPluginEmbedder for itself. The +// BrowserPluginEmbedder, in turn, forwards the requests to a +// BrowserPluginGuestManager, which creates and manages the lifetime of the new +// guest. #ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_EMBEDDER_H_ #define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_EMBEDDER_H_ @@ -34,49 +28,15 @@ class Point; namespace content { -class BrowserPluginGuest; +class BrowserPluginGuestManager; class BrowserPluginHostFactory; class WebContentsImpl; -// A browser plugin embedder provides functionality for WebContents to operate -// in the 'embedder' role. It manages list of guests inside the embedder. -// -// The embedder's WebContents manages the lifetime of the embedder. They are -// created when a renderer asks WebContents to navigate (for the first time) to -// some guest. It gets destroyed when either the WebContents goes away or there -// is a RenderViewHost swap in WebContents. class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver { public: - typedef std::map<int, WebContents*> ContainerInstanceMap; - virtual ~BrowserPluginEmbedder(); - static BrowserPluginEmbedder* Create(WebContentsImpl* web_contents, - RenderViewHost* render_view_host); - - // Creates a guest WebContents with the provided |instance_id| and |params| - // and adds it to this BrowserPluginEmbedder. If params.src is present, the - // new guest will also be navigated to the provided URL. Optionally, the new - // guest may be attached to a |guest_opener|, and may be attached to a pre- - // selected |routing_id|. - void CreateGuest(int instance_id, - int routing_id, - BrowserPluginGuest* guest_opener, - const BrowserPluginHostMsg_CreateGuest_Params& params); - - // Returns a guest browser plugin delegate by its container ID specified - // in BrowserPlugin. - BrowserPluginGuest* GetGuestByInstanceID(int instance_id) const; - - // Adds a new guest web_contents to the embedder (overridable in test). - virtual void AddGuest(int instance_id, WebContents* guest_web_contents); - void RemoveGuest(int instance_id); - - // Overrides factory for testing. Default (NULL) value indicates regular - // (non-test) environment. - static void set_factory_for_testing(BrowserPluginHostFactory* factory) { - factory_ = factory; - } + static BrowserPluginEmbedder* Create(WebContentsImpl* web_contents); // Returns the RenderViewHost at a point (|x|, |y|) asynchronously via // |callback|. We need a roundtrip to renderer process to get this @@ -86,20 +46,24 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver { int y, const WebContents::GetRenderViewHostCallback& callback); + // Overrides factory for testing. Default (NULL) value indicates regular + // (non-test) environment. + static void set_factory_for_testing(BrowserPluginHostFactory* factory) { + factory_ = factory; + } + // WebContentsObserver implementation. - virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE; virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; private: friend class TestBrowserPluginEmbedder; - BrowserPluginEmbedder(WebContentsImpl* web_contents, - RenderViewHost* render_view_host); + BrowserPluginEmbedder(WebContentsImpl* web_contents); void CleanUp(); - static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message); + BrowserPluginGuestManager* GetBrowserPluginGuestManager(); // Message handlers. @@ -109,27 +73,18 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver { void OnPluginAtPositionResponse(int instance_id, int request_id, const gfx::Point& position); - void OnUnhandledSwapBuffersACK(int instance_id, - int route_id, - int gpu_host_id, - const std::string& mailbox_name, - uint32 sync_point); // Static factory instance (always NULL for non-test). static BrowserPluginHostFactory* factory_; - // Contains guests' WebContents, mapping from their instance ids. - ContainerInstanceMap guest_web_contents_by_instance_id_; - RenderViewHost* render_view_host_; - // Map that contains outstanding queries to |GetBrowserPluginAt|. - // We need a roundtrip to renderer process to know the answer, therefore - // storing these callbacks is required. + // Map that contains outstanding queries to |GetRenderViewHostAtPosition|. + // We need a roundtrip to the renderer process to retrieve the answer, + // so we store these callbacks until we hear back from the renderer. typedef std::map<int, WebContents::GetRenderViewHostCallback> GetRenderViewHostCallbackMap; GetRenderViewHostCallbackMap pending_get_render_view_callbacks_; // Next request id for BrowserPluginMsg_PluginAtPositionRequest query. int next_get_render_view_request_id_; - int next_instance_id_; DISALLOW_COPY_AND_ASSIGN(BrowserPluginEmbedder); }; diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 5592ef6..da41a34 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc @@ -11,16 +11,19 @@ #include "base/utf_string_conversions.h" #include "content/browser/browser_plugin/browser_plugin_embedder.h" #include "content/browser/browser_plugin/browser_plugin_guest_helper.h" +#include "content/browser/browser_plugin/browser_plugin_guest_manager.h" #include "content/browser/browser_plugin/browser_plugin_host_factory.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/browser_plugin/browser_plugin_constants.h" #include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/common/content_constants_internal.h" #include "content/common/drag_messages.h" #include "content/common/gpu/gpu_messages.h" #include "content/common/view_messages.h" #include "content/port/browser/render_view_host_delegate_view.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" @@ -52,11 +55,10 @@ const size_t kNumMaxOutstandingMediaRequests = 1024; BrowserPluginGuest::BrowserPluginGuest( int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params) : WebContentsObserver(web_contents), - embedder_web_contents_(embedder_web_contents), + embedder_web_contents_(NULL), instance_id_(instance_id), damage_buffer_sequence_id_(0), damage_buffer_size_(0), @@ -71,36 +73,16 @@ BrowserPluginGuest::BrowserPluginGuest( auto_size_enabled_(params.auto_size_params.enable), max_auto_size_(params.auto_size_params.max_size), min_auto_size_(params.auto_size_params.min_size), - destroy_called_(false), current_media_access_request_id_(0) { DCHECK(web_contents); web_contents->SetDelegate(this); - - RendererPreferences* renderer_prefs = web_contents->GetMutableRendererPrefs(); - // Copy renderer preferences (and nothing else) from the embedder's - // WebContents to the guest. - // - // For GTK and Aura this is necessary to get proper renderer configuration - // values for caret blinking interval, colors related to selection and - // focus. - *renderer_prefs = *embedder_web_contents->GetMutableRendererPrefs(); - - renderer_prefs->throttle_input_events = false; - // We would like the guest to report changes to frame names so that we can - // update the BrowserPlugin's corresponding 'name' attribute. - // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed. - renderer_prefs->report_frame_name_changes = true; - // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated - // navigations still continue to function inside the app. - renderer_prefs->browser_handles_all_top_level_requests = false; + GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_, + GetWebContents()); } void BrowserPluginGuest::Destroy() { - if (destroy_called_) - return; - destroy_called_ = true; - embedder_web_contents_ = NULL; - MessageLoop::current()->DeleteSoon(FROM_HERE, web_contents()); + GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_); + delete GetWebContents(); } bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( @@ -135,13 +117,35 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( } void BrowserPluginGuest::Initialize( + WebContentsImpl* embedder_web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params) { // |render_view_host| manages the ownership of this BrowserPluginGuestHelper. - new BrowserPluginGuestHelper(this, web_contents()->GetRenderViewHost()); + new BrowserPluginGuestHelper(this, GetWebContents()->GetRenderViewHost()); + + embedder_web_contents_ = embedder_web_contents; + + RendererPreferences* renderer_prefs = + GetWebContents()->GetMutableRendererPrefs(); + // Copy renderer preferences (and nothing else) from the embedder's + // WebContents to the guest. + // + // For GTK and Aura this is necessary to get proper renderer configuration + // values for caret blinking interval, colors related to selection and + // focus. + *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs(); + + renderer_prefs->throttle_input_events = false; + // We would like the guest to report changes to frame names so that we can + // update the BrowserPlugin's corresponding 'name' attribute. + // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed. + renderer_prefs->report_frame_name_changes = true; + // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated + // navigations still continue to function inside the app. + renderer_prefs->browser_handles_all_top_level_requests = false; notification_registrar_.Add( this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, - Source<WebContents>(web_contents())); + Source<WebContents>(GetWebContents())); // Listen to embedder visibility changes so that the guest is in a 'shown' // state if both the embedder is visible and the BrowserPlugin is marked as @@ -159,8 +163,8 @@ void BrowserPluginGuest::Initialize( // Create a swapped out RenderView for the guest in the embedder render // process, so that the embedder can access the guest's window object. int guest_routing_id = - static_cast<WebContentsImpl*>(web_contents())->CreateSwappedOutRenderView( - embedder_web_contents()->GetSiteInstance()); + GetWebContents()->CreateSwappedOutRenderView( + embedder_web_contents_->GetSiteInstance()); SendMessageToEmbedder( new BrowserPluginMsg_GuestContentWindowReady(instance_id_, guest_routing_id)); @@ -168,11 +172,8 @@ void BrowserPluginGuest::Initialize( if (!params.src.empty()) OnNavigateGuest(instance_id_, params.src); - embedder_web_contents_->GetBrowserPluginEmbedder()->AddGuest(instance_id_, - web_contents()); - GetContentClient()->browser()->GuestWebContentsCreated( - web_contents(), embedder_web_contents_); + GetWebContents(), embedder_web_contents_); } BrowserPluginGuest::~BrowserPluginGuest() { @@ -181,18 +182,15 @@ BrowserPluginGuest::~BrowserPluginGuest() { // static BrowserPluginGuest* BrowserPluginGuest::Create( int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params) { RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create")); if (factory_) { return factory_->CreateBrowserPluginGuest(instance_id, - embedder_web_contents, web_contents, params); } - return new BrowserPluginGuest(instance_id, embedder_web_contents, - web_contents, params); + return new BrowserPluginGuest(instance_id, web_contents, params); } RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() { @@ -208,7 +206,7 @@ void BrowserPluginGuest::Observe(int type, const NotificationDetails& details) { switch (type) { case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: { - DCHECK_EQ(Source<WebContents>(source).ptr(), web_contents()); + DCHECK_EQ(Source<WebContents>(source).ptr(), GetWebContents()); ResourceRedirectDetails* resource_redirect_details = Details<ResourceRedirectDetails>(details).ptr(); bool is_top_level = @@ -254,7 +252,7 @@ bool BrowserPluginGuest::HandleContextMenu( void BrowserPluginGuest::RendererUnresponsive(WebContents* source) { int process_id = - web_contents()->GetRenderProcessHost()->GetID(); + GetWebContents()->GetRenderProcessHost()->GetID(); SendMessageToEmbedder( new BrowserPluginMsg_GuestUnresponsive(instance_id(), process_id)); RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung")); @@ -262,7 +260,7 @@ void BrowserPluginGuest::RendererUnresponsive(WebContents* source) { void BrowserPluginGuest::RendererResponsive(WebContents* source) { int process_id = - web_contents()->GetRenderProcessHost()->GetID(); + GetWebContents()->GetRenderProcessHost()->GetID(); SendMessageToEmbedder( new BrowserPluginMsg_GuestResponsive(instance_id(), process_id)); RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive")); @@ -279,8 +277,8 @@ bool BrowserPluginGuest::ShouldFocusPageAfterCrash() { return false; } -WebContents* BrowserPluginGuest::GetWebContents() { - return web_contents(); +WebContentsImpl* BrowserPluginGuest::GetWebContents() { + return static_cast<WebContentsImpl*>(web_contents()); } base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder( @@ -363,8 +361,6 @@ void BrowserPluginGuest::DidFailProvisionalLoad( } void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) { - if (destroy_called_) - return; msg->set_routing_id(embedder_routing_id()); embedder_web_contents_->Send(msg); } @@ -393,9 +389,9 @@ void BrowserPluginGuest::DidCommitProvisionalLoadForFrame( params.process_id = render_view_host->GetProcess()->GetID(); params.route_id = render_view_host->GetRoutingID(); params.current_entry_index = - web_contents()->GetController().GetCurrentEntryIndex(); + GetWebContents()->GetController().GetCurrentEntryIndex(); params.entry_count = - web_contents()->GetController().GetEntryCount(); + GetWebContents()->GetController().GetEntryCount(); SendMessageToEmbedder( new BrowserPluginMsg_LoadCommit(instance_id(), params)); RecordAction(UserMetricsAction("BrowserPlugin.Guest.DidNavigate")); @@ -417,17 +413,17 @@ void BrowserPluginGuest::RenderViewReady() { // here (see http://crbug.com/158151). Send(new ViewMsg_SetFocus(routing_id(), focused_)); UpdateVisibility(); - RenderViewHost* rvh = web_contents()->GetRenderViewHost(); + RenderViewHost* rvh = GetWebContents()->GetRenderViewHost(); if (auto_size_enabled_) rvh->EnableAutoResize(min_auto_size_, max_auto_size_); else rvh->DisableAutoResize(damage_view_size_); - rvh->Send(new ViewMsg_SetName(rvh->GetRoutingID(), name_)); + Send(new ViewMsg_SetName(routing_id(), name_)); } void BrowserPluginGuest::RenderViewGone(base::TerminationStatus status) { - int process_id = web_contents()->GetRenderProcessHost()->GetID(); + int process_id = GetWebContents()->GetRenderProcessHost()->GetID(); SendMessageToEmbedder( new BrowserPluginMsg_GuestGone(instance_id(), process_id, status)); switch (status) { @@ -445,6 +441,50 @@ void BrowserPluginGuest::RenderViewGone(base::TerminationStatus status) { } } +// static +void BrowserPluginGuest::AcknowledgeBufferPresent( + int route_id, + int gpu_host_id, + const std::string& mailbox_name, + uint32 sync_point) { + AcceleratedSurfaceMsg_BufferPresented_Params ack_params; + ack_params.mailbox_name = mailbox_name; + ack_params.sync_point = sync_point; + RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, + gpu_host_id, + ack_params); +} + +// static +bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest( + const IPC::Message& message) { + switch (message.type()) { + case BrowserPluginHostMsg_BuffersSwappedACK::ID: + case BrowserPluginHostMsg_DragStatusUpdate::ID: + case BrowserPluginHostMsg_Go::ID: + case BrowserPluginHostMsg_HandleInputEvent::ID: + case BrowserPluginHostMsg_LockMouse_ACK::ID: + case BrowserPluginHostMsg_NavigateGuest::ID: + case BrowserPluginHostMsg_PluginDestroyed::ID: + case BrowserPluginHostMsg_Reload::ID: + case BrowserPluginHostMsg_ResizeGuest::ID: + case BrowserPluginHostMsg_RespondPermission::ID: + case BrowserPluginHostMsg_SetAutoSize::ID: + case BrowserPluginHostMsg_SetFocus::ID: + case BrowserPluginHostMsg_SetName::ID: + case BrowserPluginHostMsg_SetVisibility::ID: + case BrowserPluginHostMsg_Stop::ID: + case BrowserPluginHostMsg_TerminateGuest::ID: + case BrowserPluginHostMsg_UnlockMouse_ACK::ID: + case BrowserPluginHostMsg_UpdateRect_ACK::ID: + return true; + default: + break; + } + return false; +} + + bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message) @@ -476,7 +516,7 @@ void BrowserPluginGuest::OnDragStatusUpdate(int instance_id, const WebDropData& drop_data, WebKit::WebDragOperationsMask mask, const gfx::Point& location) { - RenderViewHost* host = web_contents()->GetRenderViewHost(); + RenderViewHost* host = GetWebContents()->GetRenderViewHost(); switch (drag_status) { case WebKit::WebDragStatusEnter: host->DragTargetDragEnter(drop_data, location, location, mask, 0); @@ -496,7 +536,7 @@ void BrowserPluginGuest::OnDragStatusUpdate(int instance_id, } void BrowserPluginGuest::OnGo(int instance_id, int relative_index) { - web_contents()->GetController().GoToOffset(relative_index); + GetWebContents()->GetController().GoToOffset(relative_index); } void BrowserPluginGuest::OnHandleInputEvent( @@ -509,7 +549,7 @@ void BrowserPluginGuest::OnHandleInputEvent( embedder_web_contents_->GetRenderViewHost()->GetView()-> GetViewBounds().OffsetFromOrigin()); RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( - web_contents()->GetRenderViewHost()); + GetWebContents()->GetRenderViewHost()); IPC::Message* message = NULL; @@ -524,7 +564,7 @@ void BrowserPluginGuest::OnHandleInputEvent( message = new ViewMsg_HandleInputEvent(routing_id(), event, false); } - guest_rvh->Send(message); + Send(message); guest_rvh->StartHangMonitorTimeout(guest_hang_timeout_); } @@ -559,14 +599,13 @@ void BrowserPluginGuest::OnNavigateGuest( // normal web URLs are supported. No protocol handlers are installed for // other schemes (e.g., WebUI or extensions), and no permissions or bindings // can be granted to the guest process. - web_contents()->GetController().LoadURL(url, Referrer(), + GetWebContents()->GetController().LoadURL(url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); } } void BrowserPluginGuest::OnPluginDestroyed(int instance_id) { - embedder_web_contents_->GetBrowserPluginEmbedder()->RemoveGuest(instance_id); Destroy(); } @@ -574,7 +613,7 @@ void BrowserPluginGuest::OnReload(int instance_id) { // TODO(fsamuel): Don't check for repost because we don't want to show // Chromium's repost warning. We might want to implement a separate API // for registering a callback if a repost is about to happen. - web_contents()->GetController().Reload(false); + GetWebContents()->GetController().Reload(false); } void BrowserPluginGuest::OnResizeGuest( @@ -584,24 +623,21 @@ void BrowserPluginGuest::OnResizeGuest( // on RenderWidgetHost's mechanisms for flow control, so we reset those flags // here. If we are setting the size for the first time before navigating then // BrowserPluginGuest does not yet have a RenderViewHost. - if (web_contents()->GetRenderViewHost()) { + if (GetWebContents()->GetRenderViewHost()) { RenderWidgetHostImpl* render_widget_host = - RenderWidgetHostImpl::From(web_contents()->GetRenderViewHost()); + RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost()); render_widget_host->ResetSizeAndRepaintPendingFlags(); } if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) { // Invalid damage buffer, so just resize the WebContents. if (!params.view_size.IsEmpty()) - web_contents()->GetView()->SizeContents(params.view_size); + GetWebContents()->GetView()->SizeContents(params.view_size); return; } SetDamageBuffer(params); - web_contents()->GetView()->SizeContents(params.view_size); - if (params.repaint) { - web_contents()->GetRenderViewHost()->Send(new ViewMsg_Repaint( - web_contents()->GetRenderViewHost()->GetRoutingID(), - params.view_size)); - } + GetWebContents()->GetView()->SizeContents(params.view_size); + if (params.repaint) + Send(new ViewMsg_Repaint(routing_id(), params.view_size)); } void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) { @@ -615,9 +651,7 @@ void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) { if (name == name_) return; name_ = name; - web_contents()->GetRenderViewHost()->Send(new ViewMsg_SetName( - web_contents()->GetRenderViewHost()->GetRoutingID(), - name)); + Send(new ViewMsg_SetName(routing_id(), name)); } void BrowserPluginGuest::OnSetSize( @@ -633,7 +667,7 @@ void BrowserPluginGuest::OnSetSize( if (auto_size_enabled_ && (!old_auto_size_enabled || (old_max_size != max_auto_size_) || (old_min_size != min_auto_size_))) { - web_contents()->GetRenderViewHost()->EnableAutoResize( + GetWebContents()->GetRenderViewHost()->EnableAutoResize( min_auto_size_, max_auto_size_); // TODO(fsamuel): If we're changing autosize parameters, then we force // the guest to completely repaint itself, because BrowserPlugin has @@ -642,11 +676,9 @@ void BrowserPluginGuest::OnSetSize( // allocate a new damage buffer unless |max_auto_size_| has changed. // However, even in that case, layout may not change and so we may // not get a full frame worth of pixels. - web_contents()->GetRenderViewHost()->Send(new ViewMsg_Repaint( - web_contents()->GetRenderViewHost()->GetRoutingID(), - max_auto_size_)); + Send(new ViewMsg_Repaint(routing_id(), max_auto_size_)); } else if (!auto_size_enabled_ && old_auto_size_enabled) { - web_contents()->GetRenderViewHost()->DisableAutoResize( + GetWebContents()->GetRenderViewHost()->DisableAutoResize( resize_guest_params.view_size); } OnResizeGuest(instance_id_, resize_guest_params); @@ -655,26 +687,13 @@ void BrowserPluginGuest::OnSetSize( void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) { guest_visible_ = visible; if (embedder_visible_ && guest_visible_) - web_contents()->WasShown(); + GetWebContents()->WasShown(); else - web_contents()->WasHidden(); + GetWebContents()->WasHidden(); } void BrowserPluginGuest::OnStop(int instance_id) { - web_contents()->Stop(); -} - -void BrowserPluginGuest::AcknowledgeBufferPresent( - int route_id, - int gpu_host_id, - const std::string& mailbox_name, - uint32 sync_point) { - AcceleratedSurfaceMsg_BufferPresented_Params ack_params; - ack_params.mailbox_name = mailbox_name; - ack_params.sync_point = sync_point; - RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, - gpu_host_id, - ack_params); + GetWebContents()->Stop(); } void BrowserPluginGuest::OnRespondPermission( @@ -717,7 +736,7 @@ void BrowserPluginGuest::OnSwapBuffersACK(int instance_id, // is not enabled. In threaded mode, above ACK is sufficient. #if defined(OS_MACOSX) || defined(OS_WIN) RenderWidgetHostImpl* render_widget_host = - RenderWidgetHostImpl::From(web_contents()->GetRenderViewHost()); + RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost()); render_widget_host->AcknowledgeSwapBuffersToRenderer(); #endif // defined(OS_MACOSX) || defined(OS_WIN) } @@ -725,7 +744,7 @@ void BrowserPluginGuest::OnSwapBuffersACK(int instance_id, void BrowserPluginGuest::OnTerminateGuest(int instance_id) { RecordAction(UserMetricsAction("BrowserPlugin.Guest.Terminate")); base::ProcessHandle process_handle = - web_contents()->GetRenderProcessHost()->GetHandle(); + GetWebContents()->GetRenderProcessHost()->GetHandle(); if (process_handle) base::KillProcess(process_handle, RESULT_CODE_KILLED, false); } @@ -748,9 +767,7 @@ void BrowserPluginGuest::OnUpdateRectACK( int instance_id, const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { - RenderViewHost* render_view_host = web_contents()->GetRenderViewHost(); - render_view_host->Send( - new ViewMsg_UpdateRect_ACK(render_view_host->GetRoutingID())); + Send(new ViewMsg_UpdateRect_ACK(routing_id())); OnSetSize(instance_id_, auto_size_params, resize_guest_params); } @@ -770,7 +787,7 @@ void BrowserPluginGuest::OnHandleInputEventAck( WebKit::WebInputEvent::Type event_type, InputEventAckState ack_result) { RenderViewHostImpl* guest_rvh = - static_cast<RenderViewHostImpl*>(web_contents()->GetRenderViewHost()); + static_cast<RenderViewHostImpl*>(GetWebContents()->GetRenderViewHost()); guest_rvh->StopHangMonitorTimeout(); } @@ -790,7 +807,7 @@ void BrowserPluginGuest::OnShowPopup( translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin()); BrowserPluginPopupMenuHelper popup_menu_helper( embedder_web_contents_->GetRenderViewHost(), - web_contents()->GetRenderViewHost()); + GetWebContents()->GetRenderViewHost()); popup_menu_helper.ShowPopupMenu(translated_bounds, params.item_height, params.item_font_size, @@ -805,8 +822,7 @@ void BrowserPluginGuest::OnShowWidget(int route_id, const gfx::Rect& initial_pos) { gfx::Rect screen_pos(initial_pos); screen_pos.Offset(guest_screen_rect_.OffsetFromOrigin()); - static_cast<WebContentsImpl*>(web_contents())->ShowCreatedWidget(route_id, - screen_pos); + GetWebContents()->ShowCreatedWidget(route_id, screen_pos); } void BrowserPluginGuest::OnTakeFocus(bool reverse) { @@ -852,7 +868,8 @@ void BrowserPluginGuest::RequestMediaAccessPermission( base::DictionaryValue request_info; request_info.Set( - "url", base::Value::CreateStringValue(request.security_origin.spec())); + browser_plugin::kURL, + base::Value::CreateStringValue(request.security_origin.spec())); SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission( instance_id(), BrowserPluginPermissionTypeMedia, request_id, request_info)); @@ -876,7 +893,6 @@ void BrowserPluginGuest::OnUpdateRect( return; } - RenderViewHost* render_view_host = web_contents()->GetRenderViewHost(); // Only copy damage if the guest is in autosize mode and the guest's view size // is less than the maximum size or the guest's view size is equal to the // damage buffer's size and the guest's scale factor is equal to the damage @@ -887,7 +903,7 @@ void BrowserPluginGuest::OnUpdateRect( (params.view_size.width() == damage_view_size().width() && params.view_size.height() == damage_view_size().height())) && params.scale_factor == damage_buffer_scale_factor()) { - TransportDIB* dib = render_view_host->GetProcess()-> + TransportDIB* dib = GetWebContents()->GetRenderProcessHost()-> GetTransportDIB(params.bitmap); if (dib) { size_t guest_damage_buffer_size = diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h index ec20ad0..1a31551 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.h +++ b/content/browser/browser_plugin/browser_plugin_guest.h @@ -58,6 +58,7 @@ namespace content { class BrowserPluginHostFactory; class BrowserPluginEmbedder; +class BrowserPluginGuestManager; class RenderProcessHost; class RenderWidgetHostView; struct MediaStreamRequest; @@ -75,7 +76,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, static BrowserPluginGuest* Create( int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params); @@ -87,15 +87,13 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, bool OnMessageReceivedFromEmbedder(const IPC::Message& message); - void Initialize(const BrowserPluginHostMsg_CreateGuest_Params& params); + void Initialize(WebContentsImpl* embedder_web_contents, + const BrowserPluginHostMsg_CreateGuest_Params& params); void set_guest_hang_timeout_for_testing(const base::TimeDelta& timeout) { guest_hang_timeout_ = timeout; } - void set_embedder_web_contents(WebContentsImpl* web_contents) { - embedder_web_contents_ = web_contents; - } WebContentsImpl* embedder_web_contents() const { return embedder_web_contents_; } @@ -158,7 +156,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, const content::MediaResponseCallback& callback) OVERRIDE; // Exposes the protected web_contents() from WebContentsObserver. - WebContents* GetWebContents(); + WebContentsImpl* GetWebContents(); // Kill the guest process. void Terminate(); @@ -186,6 +184,10 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, const std::string& mailbox_name, uint32 sync_point); + // Returns whether BrowserPluginGuest is interested in receiving the given + // |message|. + static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message); + private: typedef std::pair<content::MediaStreamRequest, content::MediaResponseCallback> MediaStreamRequestAndCallbackPair; @@ -195,7 +197,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, friend class TestBrowserPluginGuest; BrowserPluginGuest(int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params); @@ -353,7 +354,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver, bool auto_size_enabled_; gfx::Size max_auto_size_; gfx::Size min_auto_size_; - bool destroy_called_; // A counter to generate unique request id for a media access request. // We only need the ids to be unique for a given BrowserPluginGuest. diff --git a/content/browser/browser_plugin/browser_plugin_guest_manager.cc b/content/browser/browser_plugin/browser_plugin_guest_manager.cc new file mode 100644 index 0000000..a96dcfc --- /dev/null +++ b/content/browser/browser_plugin/browser_plugin_guest_manager.cc @@ -0,0 +1,222 @@ +// Copyright (c) 2013 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_guest_manager.h" + +#include "base/command_line.h" +#include "content/browser/browser_plugin/browser_plugin_guest.h" +#include "content/browser/browser_plugin/browser_plugin_host_factory.h" +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/browser_plugin/browser_plugin_constants.h" +#include "content/common/browser_plugin/browser_plugin_messages.h" +#include "content/common/content_export.h" +#include "content/public/browser/user_metrics.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/result_codes.h" +#include "content/public/common/url_constants.h" +#include "net/base/escape.h" + +namespace content { + +// static +BrowserPluginHostFactory* BrowserPluginGuestManager::factory_ = NULL; + +BrowserPluginGuestManager::BrowserPluginGuestManager() + : next_instance_id_(browser_plugin::kInstanceIDNone) { +} + +BrowserPluginGuestManager::~BrowserPluginGuestManager() { +} + +// static +BrowserPluginGuestManager* BrowserPluginGuestManager::Create() { + if (factory_) + return factory_->CreateBrowserPluginGuestManager(); + return new BrowserPluginGuestManager(); +} + +BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest( + SiteInstance* embedder_site_instance, + int instance_id, + int routing_id, + BrowserPluginGuest* guest_opener, + const BrowserPluginHostMsg_CreateGuest_Params& params) { + SiteInstance* guest_site_instance = NULL; + int embedder_render_process_id = + embedder_site_instance->GetProcess()->GetID(); + BrowserPluginGuest* guest = + GetGuestByInstanceID(instance_id, embedder_render_process_id); + CHECK(!guest); + + // Validate that the partition id coming from the renderer is valid UTF-8, + // since we depend on this in other parts of the code, such as FilePath + // creation. If the validation fails, treat it as a bad message and kill the + // renderer process. + if (!IsStringUTF8(params.storage_partition_id)) { + content::RecordAction(UserMetricsAction("BadMessageTerminate_BPGM")); + base::KillProcess( + embedder_site_instance->GetProcess()->GetHandle(), + content::RESULT_CODE_KILLED_BAD_MESSAGE, false); + return NULL; + } + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kSitePerProcess)) { + // When --site-per-process is specified, the behavior of BrowserPlugin + // as <webview> is broken and we use it for rendering out-of-process + // iframes instead. We use the src URL sent by the renderer to find the + // right process in which to place this instance. + // Note: Since BrowserPlugin doesn't support cross-process navigation, + // the instance will stay in the initially assigned process, regardless + // of the site it is navigated to. + // TODO(nasko): Fix this, and such that cross-process navigations are + // supported. + guest_site_instance = + embedder_site_instance->GetRelatedSiteInstance(GURL(params.src)); + } else { + const std::string& host = embedder_site_instance->GetSiteURL().host(); + std::string url_encoded_partition = net::EscapeQueryParamValue( + params.storage_partition_id, false); + + if (guest_opener) { + guest_site_instance = guest_opener->GetWebContents()->GetSiteInstance(); + } else { + // The SiteInstance of a given webview tag is based on the fact that it's + // a guest process in addition to which platform application the tag + // belongs to and what storage partition is in use, rather than the URL + // that the tag is being navigated to. + GURL guest_site( + base::StringPrintf("%s://%s/%s?%s", chrome::kGuestScheme, + host.c_str(), + params.persist_storage ? "persist" : "", + url_encoded_partition.c_str())); + + // If we already have a webview tag in the same app using the same storage + // partition, we should use the same SiteInstance so the existing tag and + // the new tag can script each other. + guest_site_instance = GetGuestSiteInstance(guest_site); + if (!guest_site_instance) { + // Create the SiteInstance in a new BrowsingInstance, which will ensure + // that webview tags are also not allowed to send messages across + // different partitions. + guest_site_instance = SiteInstance::CreateForURL( + embedder_site_instance->GetBrowserContext(), guest_site); + } + } + } + + WebContentsImpl* opener_web_contents = static_cast<WebContentsImpl*>( + guest_opener ? guest_opener->GetWebContents() : NULL); + return WebContentsImpl::CreateGuest( + embedder_site_instance->GetBrowserContext(), + guest_site_instance, + routing_id, + opener_web_contents, + instance_id, + params); +} + +BrowserPluginGuest* BrowserPluginGuestManager::GetGuestByInstanceID( + int instance_id, + int embedder_render_process_id) const { + GuestInstanceMap::const_iterator it = + guest_web_contents_by_instance_id_.find(instance_id); + if (it == guest_web_contents_by_instance_id_.end()) + return NULL; + + BrowserPluginGuest* guest = + static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest(); + if (!CanEmbedderAccessGuest(embedder_render_process_id, guest)) { + // The embedder process is trying to access a guest it does not own. + content::RecordAction(UserMetricsAction("BadMessageTerminate_BPGM")); + base::KillProcess( + RenderProcessHost::FromID(embedder_render_process_id)->GetHandle(), + content::RESULT_CODE_KILLED_BAD_MESSAGE, false); + return NULL; + } + return guest; +} + +void BrowserPluginGuestManager::AddGuest(int instance_id, + WebContentsImpl* guest_web_contents) { + DCHECK(guest_web_contents_by_instance_id_.find(instance_id) == + guest_web_contents_by_instance_id_.end()); + guest_web_contents_by_instance_id_[instance_id] = guest_web_contents; +} + +void BrowserPluginGuestManager::RemoveGuest(int instance_id) { + DCHECK(guest_web_contents_by_instance_id_.find(instance_id) != + guest_web_contents_by_instance_id_.end()); + guest_web_contents_by_instance_id_.erase(instance_id); +} + +void BrowserPluginGuestManager::OnMessageReceived(const IPC::Message& message, + int render_process_id) { + if (BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(message)) { + int instance_id = 0; + // All allowed messages must have instance_id as their first parameter. + PickleIterator iter(message); + bool success = iter.ReadInt(&instance_id); + DCHECK(success); + BrowserPluginGuest* guest = + GetGuestByInstanceID(instance_id, render_process_id); + if (guest && guest->OnMessageReceivedFromEmbedder(message)) + return; + } + IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuestManager, message) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK, + OnUnhandledSwapBuffersACK) + IPC_END_MESSAGE_MAP() +} + +//static +bool BrowserPluginGuestManager::CanEmbedderAccessGuest( + int embedder_render_process_id, + BrowserPluginGuest* guest) { + // An embedder can access |guest| if the guest has not been attached and its + // opener's embedder lives in the same process as the given embedder. + if (!guest->embedder_web_contents()) { + WebContentsImpl* opener = guest->GetWebContents()->opener(); + if (!opener) + return false; + + BrowserPluginGuest* guest_opener = opener->GetBrowserPluginGuest(); + if (!guest_opener) + return false; + + return embedder_render_process_id == + guest_opener->embedder_web_contents()->GetRenderProcessHost()->GetID(); + } + + return embedder_render_process_id == + guest->embedder_web_contents()->GetRenderProcessHost()->GetID(); +} + +SiteInstance* BrowserPluginGuestManager::GetGuestSiteInstance( + const GURL& guest_site) { + for (GuestInstanceMap::const_iterator it = + guest_web_contents_by_instance_id_.begin(); + it != guest_web_contents_by_instance_id_.end(); ++it) { + if (it->second->GetSiteInstance()->GetSiteURL() == guest_site) + return it->second->GetSiteInstance(); + } + return NULL; +} + +// We only get here during teardown if we have one last buffer pending, +// otherwise the ACK is handled by the guest. +void BrowserPluginGuestManager::OnUnhandledSwapBuffersACK( + int instance_id, + int route_id, + int gpu_host_id, + const std::string& mailbox_name, + uint32 sync_point) { + BrowserPluginGuest::AcknowledgeBufferPresent(route_id, + gpu_host_id, + mailbox_name, + sync_point); +} + +} // namespace content diff --git a/content/browser/browser_plugin/browser_plugin_guest_manager.h b/content/browser/browser_plugin/browser_plugin_guest_manager.h new file mode 100644 index 0000000..a41dfc4 --- /dev/null +++ b/content/browser/browser_plugin/browser_plugin_guest_manager.h @@ -0,0 +1,112 @@ +// Copyright 2013 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. + +// A BrowserPluginGuestManager serves as a message router to BrowserPluginGuests +// for all guests within a given profile. +// Messages are routed to a particular guest instance based on an instance_id. + +#ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_MANAGER_H_ +#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_MANAGER_H_ + +#include "base/basictypes.h" +#include "base/supports_user_data.h" +#include "content/common/content_export.h" +#include "ipc/ipc_message.h" + +struct BrowserPluginHostMsg_CreateGuest_Params; +struct BrowserPluginHostMsg_ResizeGuest_Params; +class GURL; + +namespace gfx { +class Point; +} + +namespace IPC { +class Message; +} // namespace IPC + +namespace content { + +class BrowserPluginGuest; +class BrowserPluginHostFactory; +class RenderProcessHostImpl; +class SiteInstance; +class WebContents; +class WebContentsImpl; + +class CONTENT_EXPORT BrowserPluginGuestManager : + public base::SupportsUserData::Data { + public: + virtual ~BrowserPluginGuestManager(); + + static BrowserPluginGuestManager* Create(); + + // Overrides factory for testing. Default (NULL) value indicates regular + // (non-test) environment. + static void set_factory_for_testing(BrowserPluginHostFactory* factory) { + content::BrowserPluginGuestManager::factory_ = factory; + } + + // Gets the next available instance id. + int get_next_instance_id() { return ++next_instance_id_; } + + // Creates a guest WebContents with the provided |instance_id| and |params|. + // If params.src is present, the new guest will also be navigated to the + // provided URL. Optionally, the new guest may be attached to a + // |guest_opener|, and may be attached to a pre-selected |routing_id|. + BrowserPluginGuest* CreateGuest( + SiteInstance* embedder_site_instance, + int instance_id, + int routing_id, + BrowserPluginGuest* guest_opener, + const BrowserPluginHostMsg_CreateGuest_Params& params); + + // Returns a BrowserPluginGuest given an instance ID. Returns NULL if the + // guest wasn't found. If the guest doesn't belong to the given embedder, + // then NULL is returned and the embedder is killed. + BrowserPluginGuest* GetGuestByInstanceID( + int instance_id, + int embedder_render_process_id) const; + + // Adds a new |guest_web_contents| to the embedder (overridable in test). + virtual void AddGuest(int instance_id, WebContentsImpl* guest_web_contents); + void RemoveGuest(int instance_id); + + void OnMessageReceived(const IPC::Message& message, int render_process_id); + + private: + friend class TestBrowserPluginGuestManager; + + BrowserPluginGuestManager(); + + // Returns whether the given embedder process is allowed to access |guest|. + static bool CanEmbedderAccessGuest(int embedder_render_process_id, + BrowserPluginGuest* guest); + + // Returns an existing SiteInstance if the current profile has a guest of the + // given |guest_site|. + SiteInstance* GetGuestSiteInstance(const GURL& guest_site); + + // Message handlers. + void OnUnhandledSwapBuffersACK(int instance_id, + int route_id, + int gpu_host_id, + const std::string& mailbox_name, + uint32 sync_point); + + // Static factory instance (always NULL outside of tests). + static BrowserPluginHostFactory* factory_; + + // Contains guests' WebContents, mapping from their instance ids. + typedef std::map<int, WebContentsImpl*> GuestInstanceMap; + GuestInstanceMap guest_web_contents_by_instance_id_; + int next_instance_id_; + + DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuestManager); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_MANAGER_H_ + diff --git a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc index 81299ae..5802e69 100644 --- a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc +++ b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc @@ -13,6 +13,7 @@ #include "content/browser/browser_plugin/browser_plugin_host_factory.h" #include "content/browser/browser_plugin/test_browser_plugin_embedder.h" #include "content/browser/browser_plugin/test_browser_plugin_guest.h" +#include "content/browser/browser_plugin/test_browser_plugin_guest_manager.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/view_messages.h" @@ -105,26 +106,28 @@ namespace content { // BrowserPluginGuest. class TestBrowserPluginHostFactory : public BrowserPluginHostFactory { public: + virtual BrowserPluginGuestManager* + CreateBrowserPluginGuestManager() OVERRIDE { + guest_manager_instance_count_++; + if (message_loop_runner_) + message_loop_runner_->Quit(); + return new TestBrowserPluginGuestManager(); + } + virtual BrowserPluginGuest* CreateBrowserPluginGuest( int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params) OVERRIDE { return new TestBrowserPluginGuest(instance_id, - embedder_web_contents, web_contents, params); } // Also keeps track of number of instances created. virtual BrowserPluginEmbedder* CreateBrowserPluginEmbedder( - WebContentsImpl* web_contents, - RenderViewHost* render_view_host) OVERRIDE { - embedder_instance_count_++; - if (message_loop_runner_) - message_loop_runner_->Quit(); + WebContentsImpl* web_contents) OVERRIDE { - return new TestBrowserPluginEmbedder(web_contents, render_view_host); + return new TestBrowserPluginEmbedder(web_contents); } // Singleton getter. @@ -134,9 +137,9 @@ class TestBrowserPluginHostFactory : public BrowserPluginHostFactory { // Waits for at least one embedder to be created in the test. Returns true if // we have a guest, false if waiting times out. - void WaitForEmbedderCreation() { - // Check if already have created instance. - if (embedder_instance_count_ > 0) + void WaitForGuestManagerCreation() { + // Check if already have created an instance. + if (guest_manager_instance_count_ > 0) return; // Wait otherwise. message_loop_runner_ = new MessageLoopRunner(); @@ -144,7 +147,7 @@ class TestBrowserPluginHostFactory : public BrowserPluginHostFactory { } protected: - TestBrowserPluginHostFactory() : embedder_instance_count_(0) {} + TestBrowserPluginHostFactory() : guest_manager_instance_count_(0) {} virtual ~TestBrowserPluginHostFactory() {} private: @@ -152,7 +155,7 @@ class TestBrowserPluginHostFactory : public BrowserPluginHostFactory { friend struct DefaultSingletonTraits<TestBrowserPluginHostFactory>; scoped_refptr<MessageLoopRunner> message_loop_runner_; - int embedder_instance_count_; + int guest_manager_instance_count_; DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginHostFactory); }; @@ -163,12 +166,10 @@ class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory { public: virtual BrowserPluginGuest* CreateBrowserPluginGuest( int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params) OVERRIDE { BrowserPluginGuest* guest = new TestBrowserPluginGuest(instance_id, - embedder_web_contents, web_contents, params); guest->set_guest_hang_timeout_for_testing(TestTimeouts::tiny_timeout()); @@ -237,7 +238,8 @@ class BrowserPluginHostTest : public ContentBrowserTest { public: BrowserPluginHostTest() : test_embedder_(NULL), - test_guest_(NULL) {} + test_guest_(NULL), + test_guest_manager_(NULL) {} virtual void SetUp() OVERRIDE { // Override factory to create tests instances of BrowserPlugin*. @@ -245,6 +247,8 @@ class BrowserPluginHostTest : public ContentBrowserTest { TestBrowserPluginHostFactory::GetInstance()); content::BrowserPluginGuest::set_factory_for_testing( TestBrowserPluginHostFactory::GetInstance()); + content::BrowserPluginGuestManager::set_factory_for_testing( + TestBrowserPluginHostFactory::GetInstance()); ContentBrowserTest::SetUp(); } @@ -337,16 +341,21 @@ class BrowserPluginHostTest : public ContentBrowserTest { } // Wait to make sure embedder is created/attached to WebContents. - TestBrowserPluginHostFactory::GetInstance()->WaitForEmbedderCreation(); + TestBrowserPluginHostFactory::GetInstance()->WaitForGuestManagerCreation(); test_embedder_ = static_cast<TestBrowserPluginEmbedder*>( embedder_web_contents->GetBrowserPluginEmbedder()); ASSERT_TRUE(test_embedder_); - test_embedder_->WaitForGuestAdded(); + + test_guest_manager_ = static_cast<TestBrowserPluginGuestManager*>( + embedder_web_contents->GetBrowserPluginGuestManager()); + ASSERT_TRUE(test_guest_manager_); + + test_guest_manager_->WaitForGuestAdded(); // Verify that we have exactly one guest. - const BrowserPluginEmbedder::ContainerInstanceMap& instance_map = - test_embedder_->guest_web_contents_for_testing(); + const TestBrowserPluginGuestManager::GuestInstanceMap& instance_map = + test_guest_manager_->guest_web_contents_for_testing(); EXPECT_EQ(1u, instance_map.size()); WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>( @@ -358,10 +367,14 @@ class BrowserPluginHostTest : public ContentBrowserTest { TestBrowserPluginEmbedder* test_embedder() const { return test_embedder_; } TestBrowserPluginGuest* test_guest() const { return test_guest_; } + TestBrowserPluginGuestManager* test_guest_manager() const { + return test_guest_manager_; + } private: TestBrowserPluginEmbedder* test_embedder_; TestBrowserPluginGuest* test_guest_; + TestBrowserPluginGuestManager* test_guest_manager_; DISALLOW_COPY_AND_ASSIGN(BrowserPluginHostTest); }; @@ -733,10 +746,10 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) { ExecuteSyncJSFunction( test_embedder()->web_contents()->GetRenderViewHost(), StringPrintf("SetSrc('%s');", kHTMLForGuest)); - test_embedder()->WaitForGuestAdded(); + test_guest_manager()->WaitForGuestAdded(); - const BrowserPluginEmbedder::ContainerInstanceMap& instance_map = - test_embedder()->guest_web_contents_for_testing(); + const TestBrowserPluginGuestManager::GuestInstanceMap& instance_map = + test_guest_manager()->guest_web_contents_for_testing(); WebContentsImpl* test_guest_web_contents = static_cast<WebContentsImpl*>( instance_map.begin()->second); TestBrowserPluginGuest* new_test_guest = diff --git a/content/browser/browser_plugin/browser_plugin_host_factory.h b/content/browser/browser_plugin/browser_plugin_host_factory.h index fc620c4..8d83b1e 100644 --- a/content/browser/browser_plugin/browser_plugin_host_factory.h +++ b/content/browser/browser_plugin/browser_plugin_host_factory.h @@ -23,15 +23,15 @@ class WebContentsImpl; // Factory to create BrowserPlugin embedder and guest. class CONTENT_EXPORT BrowserPluginHostFactory { public: + virtual BrowserPluginGuestManager* CreateBrowserPluginGuestManager() = 0; + virtual BrowserPluginGuest* CreateBrowserPluginGuest( int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params) = 0; virtual BrowserPluginEmbedder* CreateBrowserPluginEmbedder( - WebContentsImpl* web_contents, - RenderViewHost* render_view_host) = 0; + WebContentsImpl* web_contents) = 0; protected: virtual ~BrowserPluginHostFactory() {} diff --git a/content/browser/browser_plugin/browser_plugin_message_filter.cc b/content/browser/browser_plugin/browser_plugin_message_filter.cc index 7e30db6..879c5c0 100644 --- a/content/browser/browser_plugin/browser_plugin_message_filter.cc +++ b/content/browser/browser_plugin/browser_plugin_message_filter.cc @@ -4,17 +4,24 @@ #include "content/browser/browser_plugin/browser_plugin_message_filter.h" +#include "base/supports_user_data.h" #include "content/browser/browser_plugin/browser_plugin_guest.h" +#include "content/browser/browser_plugin/browser_plugin_guest_manager.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/browser_plugin/browser_plugin_constants.h" +#include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/common/view_messages.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" namespace content { BrowserPluginMessageFilter::BrowserPluginMessageFilter( int render_process_id, - BrowserContext* browser_context) - : render_process_id_(render_process_id) { + bool is_guest) + : render_process_id_(render_process_id), + is_guest_(is_guest) { } BrowserPluginMessageFilter::~BrowserPluginMessageFilter() { @@ -24,6 +31,20 @@ BrowserPluginMessageFilter::~BrowserPluginMessageFilter() { bool BrowserPluginMessageFilter::OnMessageReceived( const IPC::Message& message, bool* message_was_ok) { + // Any message requested by a BrowserPluginGuest should be routed through + // a BrowserPluginGuestManager. + if (BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(message)) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + BrowserPluginGuestManager* guest_manager = GetBrowserPluginGuestManager(); + if (guest_manager) + guest_manager->OnMessageReceived(message, render_process_id_); + // We always swallow messages destined for BrowserPluginGuestManager because + // we're on the UI thread and fallback code is expected to be run on the IO + // thread. + return true; + } + if (!is_guest_) + return false; bool handled = true; IPC_BEGIN_MESSAGE_MAP_EX(BrowserPluginMessageFilter, message, *message_was_ok) IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_CreateWindow, @@ -33,10 +54,16 @@ bool BrowserPluginMessageFilter::OnMessageReceived( return handled; } +void BrowserPluginMessageFilter::OnDestruct() const { + BrowserThread::DeleteOnIOThread::Destruct(this); +} + void BrowserPluginMessageFilter::OverrideThreadForMessage( const IPC::Message& message, BrowserThread::ID* thread) { - if (message.type() == ViewHostMsg_CreateWindow::ID) + if (BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(message) || + (is_guest_ && message.type() == ViewHostMsg_CreateWindow::ID)) { *thread = BrowserThread::UI; + } } void BrowserPluginMessageFilter::OnCreateWindow(const IPC::Message& message) { @@ -56,4 +83,18 @@ void BrowserPluginMessageFilter::OnCreateWindow(const IPC::Message& message) { guest->OnMessageReceived(message); } +BrowserPluginGuestManager* + BrowserPluginMessageFilter::GetBrowserPluginGuestManager() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>( + RenderProcessHost::FromID(render_process_id_)); + if (!host) + return NULL; + + BrowserContext* browser_context = host->GetBrowserContext(); + return static_cast<BrowserPluginGuestManager*>( + browser_context->GetUserData( + browser_plugin::kBrowserPluginGuestManagerKeyName)); +} + } // namespace content diff --git a/content/browser/browser_plugin/browser_plugin_message_filter.h b/content/browser/browser_plugin/browser_plugin_message_filter.h index 3dba49c..a0862a7 100644 --- a/content/browser/browser_plugin/browser_plugin_message_filter.h +++ b/content/browser/browser_plugin/browser_plugin_message_filter.h @@ -10,14 +10,15 @@ struct ViewHostMsg_CreateWindow_Params; namespace content { + class BrowserContext; +class BrowserPluginGuestManager; // This class filters out incoming IPC messages for the guest renderer process // on the IPC thread before other message filters handle them. class BrowserPluginMessageFilter : public BrowserMessageFilter { public: - BrowserPluginMessageFilter(int render_process_id, - BrowserContext* browser_context); + BrowserPluginMessageFilter(int render_process_id, bool is_guest); // BrowserMessageFilter implementation. virtual void OverrideThreadForMessage( @@ -25,12 +26,19 @@ class BrowserPluginMessageFilter : public BrowserMessageFilter { BrowserThread::ID* thread) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok) OVERRIDE; + virtual void OnDestruct() const OVERRIDE; private: + friend class BrowserThread; + friend class base::DeleteHelper<BrowserPluginMessageFilter>; + virtual ~BrowserPluginMessageFilter(); void OnCreateWindow(const IPC::Message& message); + BrowserPluginGuestManager* GetBrowserPluginGuestManager(); + int render_process_id_; + int is_guest_; DISALLOW_COPY_AND_ASSIGN(BrowserPluginMessageFilter); }; diff --git a/content/browser/browser_plugin/test_browser_plugin_embedder.cc b/content/browser/browser_plugin/test_browser_plugin_embedder.cc index 61adf42..bae9943 100644 --- a/content/browser/browser_plugin/test_browser_plugin_embedder.cc +++ b/content/browser/browser_plugin/test_browser_plugin_embedder.cc @@ -4,19 +4,14 @@ #include "content/browser/browser_plugin/test_browser_plugin_embedder.h" -#include "base/time.h" #include "content/browser/browser_plugin/browser_plugin_embedder.h" -#include "content/browser/browser_plugin/browser_plugin_guest.h" -#include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/test/test_utils.h" namespace content { TestBrowserPluginEmbedder::TestBrowserPluginEmbedder( - WebContentsImpl* web_contents, - RenderViewHost* render_view_host) - : BrowserPluginEmbedder(web_contents, render_view_host), + WebContentsImpl* web_contents) + : BrowserPluginEmbedder(web_contents), last_rvh_at_position_response_(NULL) { } @@ -38,22 +33,6 @@ void TestBrowserPluginEmbedder::WaitForRenderViewHostAtPosition(int x, int y) { message_loop_runner_->Run(); } -void TestBrowserPluginEmbedder::AddGuest(int instance_id, - WebContents* guest_web_contents) { - BrowserPluginEmbedder::AddGuest(instance_id, guest_web_contents); - if (message_loop_runner_) - message_loop_runner_->Quit(); -} - -void TestBrowserPluginEmbedder::WaitForGuestAdded() { - // Check if guests were already created. - if (guest_web_contents_by_instance_id_.size() > 0) - return; - // Wait otherwise. - message_loop_runner_ = new MessageLoopRunner(); - message_loop_runner_->Run(); -} - WebContentsImpl* TestBrowserPluginEmbedder::web_contents() const { return static_cast<WebContentsImpl*>(BrowserPluginEmbedder::web_contents()); } diff --git a/content/browser/browser_plugin/test_browser_plugin_embedder.h b/content/browser/browser_plugin/test_browser_plugin_embedder.h index 1b273ab..4673f92 100644 --- a/content/browser/browser_plugin/test_browser_plugin_embedder.h +++ b/content/browser/browser_plugin/test_browser_plugin_embedder.h @@ -21,16 +21,9 @@ class WebContentsImpl; // BrowserPluginEmbedder to be used in tests. class TestBrowserPluginEmbedder : public BrowserPluginEmbedder { public: - TestBrowserPluginEmbedder(WebContentsImpl* web_contents, - RenderViewHost* render_view_host); + TestBrowserPluginEmbedder(WebContentsImpl* web_contents); virtual ~TestBrowserPluginEmbedder(); - const ContainerInstanceMap& guest_web_contents_for_testing() const { - return guest_web_contents_by_instance_id_; - } - - // Waits until at least one guest is added to this embedder. - void WaitForGuestAdded(); // Asks the renderer process for RenderViewHost at (|x|, |y|) and waits until // the response arrives. void WaitForRenderViewHostAtPosition(int x, int y); @@ -41,10 +34,6 @@ class TestBrowserPluginEmbedder : public BrowserPluginEmbedder { WebContentsImpl* web_contents() const; private: - // Overridden to intercept in test. - virtual void AddGuest(int instance_id, - WebContents* guest_web_contents) OVERRIDE; - void GetRenderViewHostCallback(RenderViewHost* rvh, int x, int y); scoped_refptr<MessageLoopRunner> message_loop_runner_; diff --git a/content/browser/browser_plugin/test_browser_plugin_guest.cc b/content/browser/browser_plugin/test_browser_plugin_guest.cc index 8b31761..867d56c 100644 --- a/content/browser/browser_plugin/test_browser_plugin_guest.cc +++ b/content/browser/browser_plugin/test_browser_plugin_guest.cc @@ -16,11 +16,9 @@ class BrowserPluginGuest; TestBrowserPluginGuest::TestBrowserPluginGuest( int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params) : BrowserPluginGuest(instance_id, - embedder_web_contents, web_contents, params), update_rect_count_(0), diff --git a/content/browser/browser_plugin/test_browser_plugin_guest.h b/content/browser/browser_plugin/test_browser_plugin_guest.h index d29fcf7..81fe77f 100644 --- a/content/browser/browser_plugin/test_browser_plugin_guest.h +++ b/content/browser/browser_plugin/test_browser_plugin_guest.h @@ -24,7 +24,6 @@ class WebContentsImpl; class TestBrowserPluginGuest : public BrowserPluginGuest { public: TestBrowserPluginGuest(int instance_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* web_contents, const BrowserPluginHostMsg_CreateGuest_Params& params); virtual ~TestBrowserPluginGuest(); diff --git a/content/browser/browser_plugin/test_browser_plugin_guest_manager.cc b/content/browser/browser_plugin/test_browser_plugin_guest_manager.cc new file mode 100644 index 0000000..2d74288 --- /dev/null +++ b/content/browser/browser_plugin/test_browser_plugin_guest_manager.cc @@ -0,0 +1,35 @@ +// Copyright (c) 2013 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/test_browser_plugin_guest_manager.h" + +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/test/test_utils.h" + +namespace content { + +TestBrowserPluginGuestManager::TestBrowserPluginGuestManager() { +} + +TestBrowserPluginGuestManager::~TestBrowserPluginGuestManager() { +} + +void TestBrowserPluginGuestManager::AddGuest( + int instance_id, + WebContentsImpl* guest_web_contents) { + BrowserPluginGuestManager::AddGuest(instance_id, guest_web_contents); + if (message_loop_runner_) + message_loop_runner_->Quit(); +} + +void TestBrowserPluginGuestManager::WaitForGuestAdded() { + // Check if guests were already created. + if (guest_web_contents_by_instance_id_.size() > 0) + return; + // Wait otherwise. + message_loop_runner_ = new MessageLoopRunner(); + message_loop_runner_->Run(); +} + +} // namespace content diff --git a/content/browser/browser_plugin/test_browser_plugin_guest_manager.h b/content/browser/browser_plugin/test_browser_plugin_guest_manager.h new file mode 100644 index 0000000..d7683cf --- /dev/null +++ b/content/browser/browser_plugin/test_browser_plugin_guest_manager.h @@ -0,0 +1,51 @@ +// Copyright (c) 2013 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_TEST_BROWSER_PLUGIN_GUEST_MANAGER_H_ +#define CONTENT_BROWSER_BROWSER_PLUGIN_TEST_BROWSER_PLUGIN_GUEST_MANAGER_H_ + +#include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" +#include "content/browser/browser_plugin/browser_plugin_guest_manager.h" +#include "content/public/test/test_utils.h" + +FORWARD_DECLARE_TEST(BrowserPluginHostTest, ReloadEmbedder); + +namespace content { + +class WebContentsImpl; + +// Test class for BrowserPluginGuestManager. +// +// Provides utilities to wait for certain state/messages in +// BrowserPluginGuestManager to be used in tests. +class TestBrowserPluginGuestManager : public BrowserPluginGuestManager { + public: + typedef BrowserPluginGuestManager::GuestInstanceMap GuestInstanceMap; + + TestBrowserPluginGuestManager(); + virtual ~TestBrowserPluginGuestManager(); + + const GuestInstanceMap& guest_web_contents_for_testing() const { + return guest_web_contents_by_instance_id_; + } + + // Waits until at least one guest is added to the guest manager. + void WaitForGuestAdded(); + + private: + // BrowserPluginHostTest.ReloadEmbedder needs access to the GuestInstanceMap. + FRIEND_TEST_ALL_PREFIXES(BrowserPluginHostTest, ReloadEmbedder); + + // Overriden to intercept in test. + virtual void AddGuest(int instance_id, + WebContentsImpl* guest_web_contents) OVERRIDE; + + scoped_refptr<MessageLoopRunner> message_loop_runner_; + DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginGuestManager); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BROWSER_PLUGIN_TEST_BROWSER_PLUGIN_GUEST_MANAGER_H_ diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index e742fac..9806638 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -487,13 +487,9 @@ void RenderProcessHostImpl::CreateMessageFilters() { MediaInternals* media_internals = MediaInternals::GetInstance();; // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages // from guests. - if (IsGuest()) { - scoped_refptr<BrowserPluginMessageFilter> bp_message_filter( - new BrowserPluginMessageFilter( - GetID(), - GetBrowserContext())); - channel_->AddFilter(bp_message_filter); - } + scoped_refptr<BrowserPluginMessageFilter> bp_message_filter( + new BrowserPluginMessageFilter(GetID(), IsGuest())); + channel_->AddFilter(bp_message_filter); scoped_refptr<RenderMessageFilter> render_message_filter( new RenderMessageFilter( diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 7ebe3c2..7161798 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -18,6 +18,7 @@ #include "cc/switches.h" #include "content/browser/browser_plugin/browser_plugin_embedder.h" #include "content/browser/browser_plugin/browser_plugin_guest.h" +#include "content/browser/browser_plugin/browser_plugin_guest_manager.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/devtools/devtools_manager_impl.h" #include "content/browser/dom_storage/dom_storage_context_impl.h" @@ -39,6 +40,7 @@ #include "content/browser/webui/generic_handler.h" #include "content/browser/webui/web_ui_controller_factory_registry.h" #include "content/browser/webui/web_ui_impl.h" +#include "content/common/browser_plugin/browser_plugin_constants.h" #include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/common/icon_messages.h" #include "content/common/ssl_status_serialization.h" @@ -367,11 +369,10 @@ WebContentsImpl* WebContentsImpl::CreateWithOpener( } // static -void WebContentsImpl::CreateGuest( +BrowserPluginGuest* WebContentsImpl::CreateGuest( BrowserContext* browser_context, SiteInstance* site_instance, int routing_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* opener_web_contents, int guest_instance_id, const BrowserPluginHostMsg_CreateGuest_Params& params) { @@ -384,7 +385,6 @@ void WebContentsImpl::CreateGuest( new_contents->browser_plugin_guest_.reset( BrowserPluginGuest::Create( guest_instance_id, - embedder_web_contents, new_contents, params)); @@ -397,7 +397,7 @@ void WebContentsImpl::CreateGuest( static_cast<RenderViewHostImpl*>( new_contents->GetRenderViewHost())->set_is_subframe(true); - new_contents->browser_plugin_guest_->Initialize(params); + return new_contents->browser_plugin_guest_.get(); } WebPreferences WebContentsImpl::GetWebkitPrefs(RenderViewHost* rvh, @@ -2424,8 +2424,7 @@ void WebContentsImpl::OnBrowserPluginAllocateInstanceID( // messages are handled in BrowserPluginEmbedder. Thus, this code will not be // executed if a BrowserPluginEmbedder exists for this WebContents. CHECK(!browser_plugin_embedder_.get()); - browser_plugin_embedder_.reset( - BrowserPluginEmbedder::Create(this, GetRenderViewHost())); + browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this)); browser_plugin_embedder_->OnMessageReceived(message); } @@ -3500,4 +3499,11 @@ BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const { return browser_plugin_embedder_.get(); } +BrowserPluginGuestManager* + WebContentsImpl::GetBrowserPluginGuestManager() const { + return static_cast<BrowserPluginGuestManager*>( + GetBrowserContext()->GetUserData( + browser_plugin::kBrowserPluginGuestManagerKeyName)); +} + } // namespace content diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index a9deb1a..e15395e 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -37,6 +37,7 @@ struct ViewMsg_PostMessage_Params; namespace content { class BrowserPluginEmbedder; class BrowserPluginGuest; +class BrowserPluginGuestManager; class ColorChooser; class DateTimeChooserAndroid; class DownloadItem; @@ -85,11 +86,10 @@ class CONTENT_EXPORT WebContentsImpl WebContentsImpl* opener() const { return opener_; } // Creates a WebContents to be used as a browser plugin guest. - static void CreateGuest( + static BrowserPluginGuest* CreateGuest( BrowserContext* browser_context, content::SiteInstance* site_instance, int routing_id, - WebContentsImpl* embedder_web_contents, WebContentsImpl* opener_web_contents, int guest_instance_id, const BrowserPluginHostMsg_CreateGuest_Params& params); @@ -166,6 +166,9 @@ class CONTENT_EXPORT WebContentsImpl // Returns embedder browser plugin object, or NULL if this WebContents is not // an embedder. BrowserPluginEmbedder* GetBrowserPluginEmbedder() const; + // Returns the BrowserPluginGuestManager object, or NULL if this web contents + // does not have a BrowserPluginGuestManager. + BrowserPluginGuestManager* GetBrowserPluginGuestManager() const; // Gets the current fullscreen render widget's routing ID. Returns // MSG_ROUTING_NONE when there is no fullscreen render widget. diff --git a/content/common/browser_plugin/browser_plugin_constants.cc b/content/common/browser_plugin/browser_plugin_constants.cc index 58fde79..6d8405b 100644 --- a/content/common/browser_plugin/browser_plugin_constants.cc +++ b/content/common/browser_plugin/browser_plugin_constants.cc @@ -72,6 +72,7 @@ const char kErrorCannotRemovePartition[] = "Cannot remove partition attribute after navigating."; // Other. +const char kBrowserPluginGuestManagerKeyName[] = "browser_plugin_guest_manager"; const int kInstanceIDNone = 0; } // namespace browser_plugin diff --git a/content/common/browser_plugin/browser_plugin_constants.h b/content/common/browser_plugin/browser_plugin_constants.h index d6f02a9..d49837d 100644 --- a/content/common/browser_plugin/browser_plugin_constants.h +++ b/content/common/browser_plugin/browser_plugin_constants.h @@ -70,6 +70,7 @@ extern const char kErrorInvalidPartition[]; extern const char kErrorCannotRemovePartition[]; // Other. +extern const char kBrowserPluginGuestManagerKeyName[]; extern const int kInstanceIDNone; } // namespace browser_plugin diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 69127b9..d3b9393 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -262,6 +262,8 @@ 'browser/browser_plugin/browser_plugin_guest.h', 'browser/browser_plugin/browser_plugin_guest_helper.cc', 'browser/browser_plugin/browser_plugin_guest_helper.h', + 'browser/browser_plugin/browser_plugin_guest_manager.cc', + 'browser/browser_plugin/browser_plugin_guest_manager.h', 'browser/browser_plugin/browser_plugin_host_factory.h', 'browser/browser_plugin/browser_plugin_message_filter.cc', 'browser/browser_plugin/browser_plugin_message_filter.h', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 7360c80..6a7b8a2 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -707,6 +707,8 @@ 'browser/browser_plugin/test_browser_plugin_embedder.h', 'browser/browser_plugin/test_browser_plugin_guest.cc', 'browser/browser_plugin/test_browser_plugin_guest.h', + 'browser/browser_plugin/test_browser_plugin_guest_manager.cc', + 'browser/browser_plugin/test_browser_plugin_guest_manager.h', 'browser/child_process_security_policy_browsertest.cc', 'browser/database_browsertest.cc', 'browser/device_orientation/device_orientation_browsertest.cc', diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 67e6459..112bd1b 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc @@ -1157,6 +1157,35 @@ gfx::Point BrowserPlugin::ToLocalCoordinates(const gfx::Point& point) const { return gfx::Point(point.x() - plugin_rect_.x(), point.y() - plugin_rect_.y()); } +// static +bool BrowserPlugin::ShouldForwardToBrowserPlugin( + const IPC::Message& message) { + switch (message.type()) { + case BrowserPluginMsg_AdvanceFocus::ID: + case BrowserPluginMsg_BuffersSwapped::ID: + case BrowserPluginMsg_GuestContentWindowReady::ID: + case BrowserPluginMsg_GuestGone::ID: + case BrowserPluginMsg_GuestResponsive::ID: + case BrowserPluginMsg_GuestUnresponsive::ID: + case BrowserPluginMsg_LoadAbort::ID: + case BrowserPluginMsg_LoadCommit::ID: + case BrowserPluginMsg_LoadRedirect::ID: + case BrowserPluginMsg_LoadStart::ID: + case BrowserPluginMsg_LoadStop::ID: + case BrowserPluginMsg_LockMouse::ID: + case BrowserPluginMsg_RequestPermission::ID: + case BrowserPluginMsg_SetCursor::ID: + case BrowserPluginMsg_ShouldAcceptTouchEvents::ID: + case BrowserPluginMsg_UnlockMouse::ID: + case BrowserPluginMsg_UpdatedName::ID: + case BrowserPluginMsg_UpdateRect::ID: + return true; + default: + break; + } + return false; +} + void BrowserPlugin::updateGeometry( const WebRect& window_rect, const WebRect& clip_rect, diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h index c218390..8e51a5b 100644 --- a/content/renderer/browser_plugin/browser_plugin.h +++ b/content/renderer/browser_plugin/browser_plugin.h @@ -141,6 +141,9 @@ class CONTENT_EXPORT BrowserPlugin : void OnEmbedderDecidedPermission(int request_id, bool allow); + // Returns whether a message should be forwarded to BrowserPlugin. + static bool ShouldForwardToBrowserPlugin(const IPC::Message& message); + // WebKit::WebPlugin implementation. virtual WebKit::WebPluginContainer* container() const OVERRIDE; virtual bool initialize(WebKit::WebPluginContainer* container) OVERRIDE; diff --git a/content/renderer/browser_plugin/browser_plugin_manager_impl.cc b/content/renderer/browser_plugin/browser_plugin_manager_impl.cc index bdc6103..ac9880e 100644 --- a/content/renderer/browser_plugin/browser_plugin_manager_impl.cc +++ b/content/renderer/browser_plugin/browser_plugin_manager_impl.cc @@ -4,6 +4,7 @@ #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h" +#include "content/common/browser_plugin/browser_plugin_constants.h" #include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/renderer/browser_plugin/browser_plugin.h" #include "content/renderer/render_thread_impl.h" @@ -42,8 +43,8 @@ bool BrowserPluginManagerImpl::Send(IPC::Message* msg) { bool BrowserPluginManagerImpl::OnMessageReceived( const IPC::Message& message) { - if (ShouldForwardToBrowserPlugin(message)) { - int instance_id = 0; + if (BrowserPlugin::ShouldForwardToBrowserPlugin(message)) { + int instance_id = browser_plugin::kInstanceIDNone; // All allowed messages must have instance_id as their first parameter. PickleIterator iter(message); bool success = iter.ReadInt(&instance_id); @@ -79,7 +80,7 @@ void BrowserPluginManagerImpl::OnPluginAtPositionRequest( const IPC::Message& message, int request_id, const gfx::Point& position) { - int instance_id = -1; + int instance_id = browser_plugin::kInstanceIDNone; IDMap<BrowserPlugin>::iterator it(&instances_); gfx::Point local_position = position; while (!it.IsAtEnd()) { @@ -117,33 +118,4 @@ void BrowserPluginManagerImpl::OnUnhandledSwap(const IPC::Message& message, 0)); } -// static -bool BrowserPluginManagerImpl::ShouldForwardToBrowserPlugin( - const IPC::Message& message) { - switch (message.type()) { - case BrowserPluginMsg_AdvanceFocus::ID: - case BrowserPluginMsg_BuffersSwapped::ID: - case BrowserPluginMsg_GuestContentWindowReady::ID: - case BrowserPluginMsg_GuestGone::ID: - case BrowserPluginMsg_GuestResponsive::ID: - case BrowserPluginMsg_GuestUnresponsive::ID: - case BrowserPluginMsg_LoadAbort::ID: - case BrowserPluginMsg_LoadCommit::ID: - case BrowserPluginMsg_LoadRedirect::ID: - case BrowserPluginMsg_LoadStart::ID: - case BrowserPluginMsg_LoadStop::ID: - case BrowserPluginMsg_LockMouse::ID: - case BrowserPluginMsg_RequestPermission::ID: - case BrowserPluginMsg_SetCursor::ID: - case BrowserPluginMsg_ShouldAcceptTouchEvents::ID: - case BrowserPluginMsg_UnlockMouse::ID: - case BrowserPluginMsg_UpdatedName::ID: - case BrowserPluginMsg_UpdateRect::ID: - return true; - default: - break; - } - return false; -} - } // namespace content diff --git a/content/renderer/browser_plugin/browser_plugin_manager_impl.h b/content/renderer/browser_plugin/browser_plugin_manager_impl.h index b20e72d..2496474 100644 --- a/content/renderer/browser_plugin/browser_plugin_manager_impl.h +++ b/content/renderer/browser_plugin/browser_plugin_manager_impl.h @@ -50,9 +50,6 @@ class BrowserPluginManagerImpl : public BrowserPluginManager { int gpu_route_id, int gpu_host_id); - // Returns whether a message should be forwarded to BrowserPlugins. - static bool ShouldForwardToBrowserPlugin(const IPC::Message& message); - int request_id_counter_; IDMap<BrowserPlugin> pending_allocate_instance_id_requests_; |