diff options
37 files changed, 471 insertions, 402 deletions
diff --git a/chrome/browser/apps/guest_view/app_view_browsertest.cc b/chrome/browser/apps/guest_view/app_view_browsertest.cc index 8ddc15d..9a6ba6b 100644 --- a/chrome/browser/apps/guest_view/app_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/app_view_browsertest.cc @@ -10,83 +10,19 @@ #include "content/public/test/test_utils.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" #include "extensions/common/switches.h" #include "extensions/test/extension_test_message_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" -namespace { - -class TestGuestViewManager : public extensions::GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) : - extensions::GuestViewManager(context), - web_contents_(NULL) {} - - content::WebContents* WaitForGuestCreated() { - if (web_contents_) - return web_contents_; - - message_loop_runner_ = new content::MessageLoopRunner; - message_loop_runner_->Run(); - return web_contents_; - } - - private: - // GuestViewManager override: - void AddGuest(int guest_instance_id, - content::WebContents* guest_web_contents) override { - extensions::GuestViewManager::AddGuest( - guest_instance_id, guest_web_contents); - web_contents_ = guest_web_contents; - - if (message_loop_runner_.get()) - message_loop_runner_->Quit(); - } - - content::WebContents* web_contents_; - scoped_refptr<content::MessageLoopRunner> message_loop_runner_; -}; - -// Test factory for creating test instances of GuestViewManager. -class TestGuestViewManagerFactory : public extensions::GuestViewManagerFactory { - public: - TestGuestViewManagerFactory() : - test_guest_view_manager_(NULL) {} - - ~TestGuestViewManagerFactory() override {} - - extensions::GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override { - return GetManager(context); - } - - TestGuestViewManager* GetManager(content::BrowserContext* context) { - if (!test_guest_view_manager_) { - test_guest_view_manager_ = new TestGuestViewManager(context); - } - return test_guest_view_manager_; - } - - private: - TestGuestViewManager* test_guest_view_manager_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory); -}; - -} // namespace - class AppViewTest : public extensions::PlatformAppBrowserTest { public: AppViewTest() { extensions::GuestViewManager::set_factory_for_testing(&factory_); } - TestGuestViewManager* GetGuestViewManager() { - return factory_.GetManager(browser()->profile()); - } - enum TestServer { NEEDS_TEST_SERVER, NO_TEST_SERVER @@ -134,7 +70,7 @@ class AppViewTest : public extensions::PlatformAppBrowserTest { extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line); } - TestGuestViewManagerFactory factory_; + extensions::TestGuestViewManagerFactory factory_; }; // Tests that <appview> is able to navigate to another installed app. diff --git a/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc b/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc index f539220..22c64a4 100644 --- a/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc @@ -6,68 +6,15 @@ #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test_utils.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" #include "extensions/test/extension_test_message_listener.h" -namespace { - -class TestGuestViewManager : public extensions::GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) - : extensions::GuestViewManager(context), web_contents_(NULL) {} - - content::WebContents* WaitForGuestCreated() { - if (web_contents_) - return web_contents_; - - message_loop_runner_ = new content::MessageLoopRunner; - message_loop_runner_->Run(); - return web_contents_; - } - - private: - // GuestViewManager override. - void AddGuest(int guest_instance_id, - content::WebContents* guest_web_contents) override { - extensions::GuestViewManager::AddGuest(guest_instance_id, - guest_web_contents); - web_contents_ = guest_web_contents; - - if (message_loop_runner_.get()) - message_loop_runner_->Quit(); - } - - content::WebContents* web_contents_; - scoped_refptr<content::MessageLoopRunner> message_loop_runner_; -}; - -// Test factory for creating test instances of GuestViewManager. -class TestGuestViewManagerFactory : public extensions::GuestViewManagerFactory { - public: - TestGuestViewManagerFactory() : test_guest_view_manager_(NULL) {} - - ~TestGuestViewManagerFactory() override {} - - extensions::GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override { - return GetManager(context); - } - - TestGuestViewManager* GetManager(content::BrowserContext* context) { - if (!test_guest_view_manager_) { - test_guest_view_manager_ = new TestGuestViewManager(context); - } - return test_guest_view_manager_; - } - - private: - TestGuestViewManager* test_guest_view_manager_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory); -}; - -} // namespace +using extensions::ExtensionsGuestViewManagerDelegate; +using extensions::GuestViewManager; +using extensions::TestGuestViewManager; class ExtensionViewTest : public extensions::PlatformAppBrowserTest { public: @@ -75,8 +22,20 @@ class ExtensionViewTest : public extensions::PlatformAppBrowserTest { extensions::GuestViewManager::set_factory_for_testing(&factory_); } - TestGuestViewManager* GetGuestViewManager() { - return factory_.GetManager(browser()->profile()); + extensions::TestGuestViewManager* GetGuestViewManager() { + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(browser()->profile())); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + browser()->profile(), + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate( + browser()->profile())))); + } + return manager; } void TestHelper(const std::string& test_name, @@ -111,7 +70,7 @@ class ExtensionViewTest : public extensions::PlatformAppBrowserTest { extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line); } - TestGuestViewManagerFactory factory_; + extensions::TestGuestViewManagerFactory factory_; }; // Tests that <extensionview> can be created and added to the DOM. diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 7318ef8..4eb7744 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc @@ -36,6 +36,7 @@ #include "extensions/browser/api/declarative/test_rules_registry.h" #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" #include "extensions/browser/app_window/native_app_window.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" #include "extensions/browser/guest_view/test_guest_view_manager.h" @@ -67,6 +68,9 @@ #endif using extensions::ContextMenuMatcher; +using extensions::ExtensionsGuestViewManagerDelegate; +using extensions::GuestViewManager; +using extensions::TestGuestViewManager; using extensions::MenuItem; using prerender::PrerenderLinkManager; using prerender::PrerenderLinkManagerFactory; @@ -816,10 +820,20 @@ class WebViewTest : public extensions::PlatformAppBrowserTest { return embedder_web_contents_; } - extensions::TestGuestViewManager* GetGuestViewManager() { - return static_cast<extensions::TestGuestViewManager*>( - extensions::TestGuestViewManager::FromBrowserContext( - browser()->profile())); + TestGuestViewManager* GetGuestViewManager() { + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(browser()->profile())); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + browser()->profile(), + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate( + browser()->profile())))); + } + return manager; } WebViewTest() : guest_web_contents_(NULL), diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc index 89a6099..bb24c91 100644 --- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc @@ -23,9 +23,11 @@ #include "content/public/test/browser_test_utils.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_base.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" #include "extensions/test/extension_test_message_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/base/ime/composition_text.h" @@ -34,88 +36,9 @@ #include "ui/events/keycodes/keyboard_codes.h" using extensions::AppWindow; - -class TestGuestViewManager : public extensions::GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) - : GuestViewManager(context), - guest_add_count_(0), - guest_remove_count_(0), - web_contents_(NULL) {} - - content::WebContents* WaitForGuestAdded() { - if (web_contents_) - return web_contents_; - - add_message_loop_runner_ = new content::MessageLoopRunner; - add_message_loop_runner_->Run(); - return web_contents_; - } - - // Waits so that at least |expected_remove_count| guests' creation - // has been seen by this manager. - void WaitForGuestRemoved(size_t expected_remove_count) { - if (guest_remove_count_ >= expected_remove_count) - return; - - remove_message_loop_runner_ = new content::MessageLoopRunner; - remove_message_loop_runner_->Run(); - } - - size_t guest_add_count() { return guest_add_count_; } - - private: - // GuestViewManager override: - void AddGuest(int guest_instance_id, - content::WebContents* guest_web_contents) override { - GuestViewManager::AddGuest(guest_instance_id, guest_web_contents); - web_contents_ = guest_web_contents; - ++guest_add_count_; - - if (add_message_loop_runner_.get()) - add_message_loop_runner_->Quit(); - } - - void RemoveGuest(int guest_instance_id) override { - GuestViewManager::RemoveGuest(guest_instance_id); - ++guest_remove_count_; - - if (remove_message_loop_runner_.get()) - remove_message_loop_runner_->Quit(); - } - - size_t guest_add_count_; - size_t guest_remove_count_; - content::WebContents* web_contents_; - scoped_refptr<content::MessageLoopRunner> add_message_loop_runner_; - scoped_refptr<content::MessageLoopRunner> remove_message_loop_runner_; -}; - -// Test factory for creating test instances of GuestViewManager. -class TestGuestViewManagerFactory : public extensions::GuestViewManagerFactory { - public: - TestGuestViewManagerFactory() : - test_guest_view_manager_(NULL) {} - - ~TestGuestViewManagerFactory() override {} - - extensions::GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override { - return GetManager(context); - } - - TestGuestViewManager* GetManager(content::BrowserContext* context) { - if (!test_guest_view_manager_) { - test_guest_view_manager_ = new TestGuestViewManager(context); - } - return test_guest_view_manager_; - } - - private: - TestGuestViewManager* test_guest_view_manager_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory); -}; +using extensions::ExtensionsGuestViewManagerDelegate; +using extensions::GuestViewManager; +using extensions::TestGuestViewManager; class WebViewInteractiveTest : public extensions::PlatformAppBrowserTest { @@ -130,7 +53,19 @@ class WebViewInteractiveTest } TestGuestViewManager* GetGuestViewManager() { - return factory_.GetManager(browser()->profile()); + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(browser()->profile())); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + browser()->profile(), + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate( + browser()->profile())))); + } + return manager; } void MoveMouseInsideWindowWithListener(gfx::Point point, @@ -284,11 +219,9 @@ class WebViewInteractiveTest ASSERT_TRUE(done_listener); ASSERT_TRUE(done_listener->WaitUntilSatisfied()); - guest_web_contents_ = GetGuestViewManager()->WaitForGuestAdded(); + guest_web_contents_ = GetGuestViewManager()->WaitForSingleGuestCreated(); } - void RunTest(const std::string& app_name) { - } void SetupTest(const std::string& app_name, const std::string& guest_url_spec) { ASSERT_TRUE(StartEmbeddedTestServer()); @@ -547,7 +480,7 @@ class WebViewInteractiveTest } protected: - TestGuestViewManagerFactory factory_; + extensions::TestGuestViewManagerFactory factory_; content::WebContents* guest_web_contents_; content::WebContents* embedder_web_contents_; gfx::Point corner_; @@ -900,13 +833,13 @@ IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, TestHelper("testNewWindowOpenerDestroyedWhileUnattached", "web_view/newwindow", NEEDS_TEST_SERVER); - ASSERT_EQ(2u, GetGuestViewManager()->guest_add_count()); + ASSERT_EQ(2, GetGuestViewManager()->num_guests_created()); // We have two guests in this test, one is the intial one, the other // is the newwindow one. // Before the embedder goes away, both the guests should go away. // This ensures that unattached guests are gone if opener is gone. - GetGuestViewManager()->WaitForGuestRemoved(2u); + GetGuestViewManager()->WaitForAllGuestsDeleted(); } IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) { diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc index a0177c5..afdd741 100644 --- a/chrome/browser/chromeos/login/helper.cc +++ b/chrome/browser/chromeos/login/helper.cc @@ -66,7 +66,7 @@ bool FindGuestByPartitionName(const std::string& partition_name, content::StoragePartition* GetPartition(content::WebContents* embedder, const std::string& partition_name) { extensions::GuestViewManager* manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( + extensions::GuestViewManager::FromBrowserContext( embedder->GetBrowserContext()); if (!manager) return nullptr; diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc index 7bcf360..03abc79 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc +++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc @@ -132,7 +132,7 @@ void ChromeWebViewGuestDelegate::OnGuestDestroyed() { MenuManager* menu_manager = MenuManager::Get( Profile::FromBrowserContext(web_view_guest()->browser_context())); menu_manager->RemoveAllContextItems(MenuItem::ExtensionKey( - web_view_guest()->owner_extension_id(), + web_view_guest()->owner_host(), web_view_guest()->view_instance_id())); } diff --git a/chrome/browser/printing/print_view_manager_common.cc b/chrome/browser/printing/print_view_manager_common.cc index 37f8d09..7f8ad12 100644 --- a/chrome/browser/printing/print_view_manager_common.cc +++ b/chrome/browser/printing/print_view_manager_common.cc @@ -37,7 +37,7 @@ bool StoreFullPagePlugin(content::WebContents** result, content::WebContents* GetWebContentsToUse(content::WebContents* contents) { #if defined(ENABLE_EXTENSIONS) extensions::GuestViewManager* guest_view_manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( + extensions::GuestViewManager::FromBrowserContext( contents->GetBrowserContext()); if (guest_view_manager) { guest_view_manager->ForEachGuest( diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index 1c79bf9..a363530 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc @@ -415,7 +415,7 @@ HostContentSettingsMap* OffTheRecordProfileImpl::GetHostContentSettingsMap() { content::BrowserPluginGuestManager* OffTheRecordProfileImpl::GetGuestManager() { #if defined(ENABLE_EXTENSIONS) - return extensions::GuestViewManager::FromBrowserContextIfAvailable(this); + return extensions::GuestViewManager::FromBrowserContext(this); #else return NULL; #endif diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 106a677..1ddc4fc 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -1053,7 +1053,7 @@ HostContentSettingsMap* ProfileImpl::GetHostContentSettingsMap() { content::BrowserPluginGuestManager* ProfileImpl::GetGuestManager() { #if defined(ENABLE_EXTENSIONS) - return extensions::GuestViewManager::FromBrowserContextIfAvailable(this); + return extensions::GuestViewManager::FromBrowserContext(this); #else return NULL; #endif diff --git a/chrome/browser/signin/signin_header_helper.cc b/chrome/browser/signin/signin_header_helper.cc index 0387202..83e502b 100644 --- a/chrome/browser/signin/signin_header_helper.cc +++ b/chrome/browser/signin/signin_header_helper.cc @@ -250,7 +250,7 @@ bool AppendMirrorRequestHeaderIfPossible( // embedded in a webui page, otherwise user may end up with a blank page as // gaia uses the header to decide whether it returns 204 for certain end // points. - if (is_guest && webview_info.owner_extension_id.empty()) + if (is_guest && webview_info.owner_host.empty()) return false; #endif // !OS_ANDROID && !OS_IOS diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc index 26fdafa..b2ef8e0 100644 --- a/chrome/browser/ui/tab_contents/core_tab_helper.cc +++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc @@ -92,9 +92,8 @@ bool CoreTabHelper::GetStatusTextForWebContents( tracked_objects::ScopedTracker tracking_profile1( FROM_HERE_WITH_EXPLICIT_FUNCTION( "467185 CoreTabHelper::GetStatusTextForWebContents1")); - auto guest_manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( - source->GetBrowserContext()); + auto guest_manager = extensions::GuestViewManager::FromBrowserContext( + source->GetBrowserContext()); if (!source->IsLoading() || source->GetLoadState().state == net::LOAD_STATE_IDLE) { // TODO(robliao): Remove ScopedTracker below once https://crbug.com/467185 diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc index e807990..e38d985 100644 --- a/chrome/browser/ui/webui/signin/inline_login_ui.cc +++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc @@ -138,7 +138,7 @@ content::RenderFrameHost* InlineLoginUI::GetAuthFrame( #endif if (is_webview) { extensions::GuestViewManager* manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( + extensions::GuestViewManager::FromBrowserContext( web_contents->GetBrowserContext()); if (manager) { manager->ForEachGuest(web_contents, diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index 84c2e30..62cb0bb 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc @@ -955,7 +955,7 @@ HostContentSettingsMap* TestingProfile::GetHostContentSettingsMap() { content::BrowserPluginGuestManager* TestingProfile::GetGuestManager() { #if defined(ENABLE_EXTENSIONS) - return extensions::GuestViewManager::FromBrowserContextIfAvailable(this); + return extensions::GuestViewManager::FromBrowserContext(this); #else return NULL; #endif diff --git a/extensions/browser/api/guest_view/guest_view_internal_api.cc b/extensions/browser/api/guest_view/guest_view_internal_api.cc index bfe4fb5..aea9c8e 100644 --- a/extensions/browser/api/guest_view/guest_view_internal_api.cc +++ b/extensions/browser/api/guest_view/guest_view_internal_api.cc @@ -6,12 +6,15 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_base.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/common/api/guest_view_internal.h" #include "extensions/common/guest_view/guest_view_constants.h" #include "extensions/common/permissions/permissions_data.h" +using guestview::GuestViewManagerDelegate; + namespace guest_view_internal = extensions::core_api::guest_view_internal; namespace extensions { @@ -31,6 +34,12 @@ bool GuestViewInternalCreateGuestFunction::RunAsync() { // if we don't already have one. GuestViewManager* guest_view_manager = GuestViewManager::FromBrowserContext(browser_context()); + if (!guest_view_manager) { + guest_view_manager = GuestViewManager::CreateWithDelegate( + browser_context(), + scoped_ptr<GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate(context_))); + } GuestViewManager::WebContentsCreatedCallback callback = base::Bind(&GuestViewInternalCreateGuestFunction::CreateGuestCallback, diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc index 328ef0b..386ab0d 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.cc +++ b/extensions/browser/guest_view/app_view/app_view_guest.cc @@ -279,7 +279,7 @@ void AppViewGuest::LaunchAppAndFireEvent( scoped_ptr<base::DictionaryValue> embed_request(new base::DictionaryValue()); embed_request->SetInteger(appview::kGuestInstanceID, guest_instance_id()); - embed_request->SetString(appview::kEmbedderID, owner_extension_id()); + embed_request->SetString(appview::kEmbedderID, owner_host()); embed_request->Set(appview::kData, data.release()); AppRuntimeEventRouter::DispatchOnEmbedRequestedEvent( browser_context(), embed_request.Pass(), extension_host->extension()); diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc new file mode 100644 index 0000000..975d962 --- /dev/null +++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc @@ -0,0 +1,93 @@ +// Copyright 2015 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 "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" + +#include "content/public/browser/browser_context.h" +#include "content/public/browser/render_process_host.h" +#include "extensions/browser/event_router.h" +#include "extensions/browser/guest_view/app_view/app_view_guest.h" +#include "extensions/browser/guest_view/extension_options/extension_options_guest.h" +#include "extensions/browser/guest_view/extension_view/extension_view_guest.h" +#include "extensions/browser/guest_view/guest_view_base.h" +#include "extensions/browser/guest_view/guest_view_manager.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" +#include "extensions/browser/guest_view/surface_worker/surface_worker_guest.h" +#include "extensions/browser/guest_view/web_view/web_view_guest.h" +#include "extensions/browser/process_manager.h" +#include "extensions/browser/process_map.h" +#include "extensions/common/features/feature.h" +#include "extensions/common/features/feature_provider.h" + +namespace extensions { + +ExtensionsGuestViewManagerDelegate::ExtensionsGuestViewManagerDelegate( + content::BrowserContext* context) + : context_(context) { +} + +ExtensionsGuestViewManagerDelegate::~ExtensionsGuestViewManagerDelegate() { +} + +void ExtensionsGuestViewManagerDelegate::DispatchEvent( + const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id) { + EventFilteringInfo info; + info.SetInstanceID(instance_id); + scoped_ptr<base::ListValue> event_args(new base::ListValue()); + event_args->Append(args.release()); + + EventRouter::DispatchEvent( + guest->owner_web_contents(), + guest->browser_context(), + guest->owner_host(), + event_name, + event_args.Pass(), + EventRouter::USER_GESTURE_UNKNOWN, + info); +} + +bool ExtensionsGuestViewManagerDelegate::IsGuestAvailableToContext( + extensions::GuestViewBase* guest) { + const Feature* feature = + FeatureProvider::GetAPIFeature(guest->GetAPINamespace()); + CHECK(feature); + + ProcessMap* process_map = ProcessMap::Get(context_); + CHECK(process_map); + + const Extension* owner_extension = ProcessManager::Get(context_)-> + GetExtensionForWebContents(guest->owner_web_contents()); + + // Ok for |owner_extension| to be nullptr, the embedder might be WebUI. + Feature::Availability availability = feature->IsAvailableToContext( + owner_extension, + process_map->GetMostLikelyContextType( + owner_extension, + guest->owner_web_contents()->GetRenderProcessHost()->GetID()), + guest->GetOwnerSiteURL()); + + return availability.is_available(); +} + +bool ExtensionsGuestViewManagerDelegate::IsOwnedByExtension( + extensions::GuestViewBase* guest) { + return !!ProcessManager::Get(context_)-> + GetExtensionForWebContents(guest->owner_web_contents()); +} + +void ExtensionsGuestViewManagerDelegate::RegisterAdditionalGuestViewTypes() { + extensions::GuestViewManager* manager = + extensions::GuestViewManager::FromBrowserContext(context_); + manager->RegisterGuestViewType<AppViewGuest>(); + manager->RegisterGuestViewType<ExtensionOptionsGuest>(); + manager->RegisterGuestViewType<ExtensionViewGuest>(); + manager->RegisterGuestViewType<MimeHandlerViewGuest>(); + manager->RegisterGuestViewType<SurfaceWorkerGuest>(); + manager->RegisterGuestViewType<WebViewGuest>(); +} + +} // namespace extensions diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.h b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.h new file mode 100644 index 0000000..1b47820 --- /dev/null +++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.h @@ -0,0 +1,44 @@ +// Copyright 2015 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 EXTENSIONS_BROWSER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_MANAGER_DELEGATE_H_ +#define EXTENSIONS_BROWSER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_MANAGER_DELEGATE_H_ + +#include "extensions/browser/guest_view/guest_view_manager_delegate.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace extensions { +class GuestViewBase; +class GuestViewManager; +} // namespace extensions + +namespace extensions { + +// ExtensionsGuestViewManagerDelegate implements GuestViewManager functionality +// specific to Chromium builds that include the extensions module. +class ExtensionsGuestViewManagerDelegate + : public guestview::GuestViewManagerDelegate { + public: + explicit ExtensionsGuestViewManagerDelegate(content::BrowserContext* context); + ~ExtensionsGuestViewManagerDelegate() override; + + // GuestViewManagerDelegate implementation. + void DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id) override; + bool IsGuestAvailableToContext(extensions::GuestViewBase* guest) override; + bool IsOwnedByExtension(extensions::GuestViewBase* guest) override; + void RegisterAdditionalGuestViewTypes() override; + + private: + content::BrowserContext* const context_; +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_MANAGER_DELEGATE_H_ diff --git a/extensions/browser/guest_view/extensions_guest_view_message_filter.cc b/extensions/browser/guest_view/extensions_guest_view_message_filter.cc index 215bf81..7f52840 100644 --- a/extensions/browser/guest_view/extensions_guest_view_message_filter.cc +++ b/extensions/browser/guest_view/extensions_guest_view_message_filter.cc @@ -8,6 +8,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_base.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_constants.h" @@ -22,6 +23,7 @@ using content::BrowserContext; using content::BrowserThread; using content::RenderFrameHost; using content::WebContents; +using guestview::GuestViewManagerDelegate; namespace extensions { @@ -93,7 +95,12 @@ void ExtensionsGuestViewMessageFilter::OnCreateMimeHandlerViewGuest( // Since we are creating a new guest, we will create a GuestViewManager // if we don't already have one. auto manager = GuestViewManager::FromBrowserContext(browser_context_); - DCHECK(manager); + if (!manager) { + manager = GuestViewManager::CreateWithDelegate( + browser_context_, + scoped_ptr<GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate(browser_context_))); + } auto rfh = RenderFrameHost::FromID(render_process_id_, render_frame_id); auto embedder_web_contents = WebContents::FromRenderFrameHost(rfh); @@ -124,8 +131,7 @@ void ExtensionsGuestViewMessageFilter::OnResizeGuest( int render_frame_id, int element_instance_id, const gfx::Size& new_size) { - auto manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context_); + auto manager = GuestViewManager::FromBrowserContext(browser_context_); // We should have a GuestViewManager at this point. If we don't then the // embedder is misbehaving. if (!manager) @@ -162,8 +168,7 @@ void ExtensionsGuestViewMessageFilter::MimeHandlerViewGuestCreatedCallback( base::DictionaryValue attach_params; attach_params.SetInteger(guestview::kElementWidth, element_size.width()); attach_params.SetInteger(guestview::kElementHeight, element_size.height()); - auto manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context_); + auto manager = GuestViewManager::FromBrowserContext(browser_context_); CHECK(manager); manager->AttachGuest(embedder_render_process_id, element_instance_id, diff --git a/extensions/browser/guest_view/guest_view_base.cc b/extensions/browser/guest_view/guest_view_base.cc index 134c326..48b9b25 100644 --- a/extensions/browser/guest_view/guest_view_base.cc +++ b/extensions/browser/guest_view/guest_view_base.cc @@ -146,7 +146,7 @@ GuestViewBase::GuestViewBase(content::WebContents* owner_web_contents) : owner_web_contents_(owner_web_contents), browser_context_(owner_web_contents->GetBrowserContext()), guest_instance_id_( - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> + GuestViewManager::FromBrowserContext(browser_context_)-> GetNextInstanceID()), view_instance_id_(guestview::kInstanceIDNone), element_instance_id_(guestview::kInstanceIDNone), @@ -157,6 +157,9 @@ GuestViewBase::GuestViewBase(content::WebContents* owner_web_contents) is_full_page_plugin_(false), guest_proxy_routing_id_(MSG_ROUTING_NONE), weak_ptr_factory_(this) { + owner_host_ = GuestViewManager::FromBrowserContext(browser_context_)-> + IsOwnedByExtension(this) ? + owner_web_contents->GetLastCommittedURL().host() : std::string(); } void GuestViewBase::Init(const base::DictionaryValue& create_params, @@ -165,8 +168,8 @@ void GuestViewBase::Init(const base::DictionaryValue& create_params, return; initialized_ = true; - if (!GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> - IsGuestAvailableToContext(this, &owner_extension_id_)) { + if (!GuestViewManager::FromBrowserContext(browser_context_)-> + IsGuestAvailableToContext(this)) { // The derived class did not create a WebContents so this class serves no // purpose. Let's self-destruct. delete this; @@ -208,7 +211,7 @@ void GuestViewBase::InitWithWebContents( guest_web_contents->SetDelegate(this); webcontents_guestview_map.Get().insert( std::make_pair(guest_web_contents, this)); - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> + GuestViewManager::FromBrowserContext(browser_context_)-> AddGuest(guest_instance_id_, guest_web_contents); // Populate the view instance ID if we have it on creation. @@ -331,7 +334,7 @@ GuestViewBase* GuestViewBase::From(int owner_process_id, return nullptr; content::WebContents* guest_web_contents = - GuestViewManager::FromBrowserContextIfAvailable( + GuestViewManager::FromBrowserContext( host->GetBrowserContext())-> GetGuestByInstanceIDSafely(guest_instance_id, owner_process_id); if (!guest_web_contents) @@ -370,8 +373,7 @@ bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const { content::WebContents* GuestViewBase::CreateNewGuestWindow( const content::WebContents::CreateParams& create_params) { - auto guest_manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context()); + auto guest_manager = GuestViewManager::FromBrowserContext(browser_context()); return guest_manager->CreateGuestWithWebContentsParams( GetViewType(), owner_web_contents(), @@ -399,8 +401,7 @@ void GuestViewBase::DidAttach(int guest_proxy_routing_id) { } void GuestViewBase::DidDetach() { - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> - DetachGuest(this); + GuestViewManager::FromBrowserContext(browser_context_)->DetachGuest(this); StopTrackingEmbedderZoomLevel(); owner_web_contents()->Send(new GuestViewMsg_GuestDetached( element_instance_id_)); @@ -450,7 +451,7 @@ void GuestViewBase::Destroy() { guest_host_ = nullptr; webcontents_guestview_map.Get().erase(web_contents()); - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> + GuestViewManager::FromBrowserContext(browser_context_)-> RemoveGuest(guest_instance_id_); pending_events_.clear(); @@ -488,6 +489,9 @@ void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents, owner_web_contents_ = embedder_web_contents; owner_contents_observer_.reset( new OwnerContentsObserver(this, embedder_web_contents)); + owner_host_ = GuestViewManager::FromBrowserContext(browser_context_)-> + IsOwnedByExtension(this) ? + owner_web_contents()->GetLastCommittedURL().host() : std::string(); } // Start tracking the new embedder's zoom level. diff --git a/extensions/browser/guest_view/guest_view_base.h b/extensions/browser/guest_view/guest_view_base.h index 7969cb9..6252e6c 100644 --- a/extensions/browser/guest_view/guest_view_base.h +++ b/extensions/browser/guest_view/guest_view_base.h @@ -241,14 +241,6 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, // Returns the instance ID of the GuestViewBase's element. int element_instance_id() const { return element_instance_id_; } - // Returns the extension ID of the embedder. - const std::string& owner_extension_id() const { - return owner_extension_id_; - } - - // Returns whether this GuestView is embedded in an extension/app. - bool in_extension() const { return !owner_extension_id_.empty(); } - bool can_owner_receive_events() const { return !!view_instance_id_; } // Returns the user browser context of the embedder. @@ -261,6 +253,10 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, // Returns the URL of the owner WebContents. const GURL& GetOwnerSiteURL() const; + // Returns the host of the owner WebContents. For extensions, this is the + // extension ID. + std::string owner_host() const { return owner_host_; } + // Whether the guest view is inside a plugin document. bool is_full_page_plugin() const { return is_full_page_plugin_; } @@ -381,7 +377,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, // |owner_web_contents_|. If |owner_web_contents_| is destroyed then this // guest will also self-destruct. content::WebContents* owner_web_contents_; - std::string owner_extension_id_; + std::string owner_host_; content::BrowserContext* const browser_context_; // |guest_instance_id_| is a profile-wide unique identifier for a guest diff --git a/extensions/browser/guest_view/guest_view_event.cc b/extensions/browser/guest_view/guest_view_event.cc index 3964155..00b0af3 100644 --- a/extensions/browser/guest_view/guest_view_event.cc +++ b/extensions/browser/guest_view/guest_view_event.cc @@ -4,8 +4,8 @@ #include "extensions/browser/guest_view/guest_view_event.h" -#include "extensions/browser/event_router.h" #include "extensions/browser/guest_view/guest_view_base.h" +#include "extensions/browser/guest_view/guest_view_manager.h" namespace extensions { @@ -19,19 +19,8 @@ GuestViewEvent::~GuestViewEvent() { } void GuestViewEvent::Dispatch(GuestViewBase* guest, int instance_id) { - EventFilteringInfo info; - info.SetInstanceID(instance_id); - scoped_ptr<base::ListValue> args(new base::ListValue()); - args->Append(args_.release()); - - EventRouter::DispatchEvent( - guest->owner_web_contents(), - guest->browser_context(), - guest->owner_extension_id(), - name_, - args.Pass(), - EventRouter::USER_GESTURE_UNKNOWN, - info); + GuestViewManager::FromBrowserContext(guest->browser_context())-> + DispatchEvent(name_, args_.Pass(), guest, instance_id); delete this; } diff --git a/extensions/browser/guest_view/guest_view_event.h b/extensions/browser/guest_view/guest_view_event.h index 1d557a0..c9c8cb8 100644 --- a/extensions/browser/guest_view/guest_view_event.h +++ b/extensions/browser/guest_view/guest_view_event.h @@ -14,8 +14,8 @@ namespace extensions { class GuestViewBase; -// A GuestViewEvent is a wrapper class for an extension event. -// GuestViewEvents may be queued until the guest is attached to a conatiner. +// A GuestViewEvent is a wrapper class for a GuestView event. +// GuestViewEvents may be queued until the guest is attached to a container. // This wrapper class holds all the necessary information to fire the event // on attachment. GuestViewEvents are owned by GuestViewBase. class GuestViewEvent { diff --git a/extensions/browser/guest_view/guest_view_manager.cc b/extensions/browser/guest_view/guest_view_manager.cc index dd2ad1c..0d6b28b 100644 --- a/extensions/browser/guest_view/guest_view_manager.cc +++ b/extensions/browser/guest_view/guest_view_manager.cc @@ -14,18 +14,9 @@ #include "content/public/common/child_process_host.h" #include "content/public/common/result_codes.h" #include "content/public/common/url_constants.h" -#include "extensions/browser/guest_view/app_view/app_view_guest.h" -#include "extensions/browser/guest_view/extension_options/extension_options_guest.h" -#include "extensions/browser/guest_view/extension_view/extension_view_guest.h" #include "extensions/browser/guest_view/guest_view_base.h" +#include "extensions/browser/guest_view/guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" -#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" -#include "extensions/browser/guest_view/surface_worker/surface_worker_guest.h" -#include "extensions/browser/guest_view/web_view/web_view_guest.h" -#include "extensions/browser/process_manager.h" -#include "extensions/browser/process_map.h" -#include "extensions/common/features/feature.h" -#include "extensions/common/features/feature_provider.h" #include "extensions/common/guest_view/guest_view_constants.h" #include "net/base/escape.h" #include "url/gurl.h" @@ -33,29 +24,35 @@ using content::BrowserContext; using content::SiteInstance; using content::WebContents; +using guestview::GuestViewManagerDelegate; namespace extensions { // static GuestViewManagerFactory* GuestViewManager::factory_ = nullptr; -GuestViewManager::GuestViewManager(content::BrowserContext* context) - : current_instance_id_(0), last_instance_id_removed_(0), context_(context) { +GuestViewManager::GuestViewManager( + content::BrowserContext* context, + scoped_ptr<GuestViewManagerDelegate> delegate) + : current_instance_id_(0), + last_instance_id_removed_(0), + context_(context), + delegate_(delegate.Pass()) { } GuestViewManager::~GuestViewManager() {} // static -GuestViewManager* GuestViewManager::FromBrowserContext( - BrowserContext* context) { - GuestViewManager* guest_manager = - static_cast<GuestViewManager*>(context->GetUserData( - guestview::kGuestViewManagerKeyName)); +GuestViewManager* GuestViewManager::CreateWithDelegate( + BrowserContext* context, + scoped_ptr<GuestViewManagerDelegate> delegate) { + GuestViewManager* guest_manager = FromBrowserContext(context); if (!guest_manager) { if (factory_) { - guest_manager = factory_->CreateGuestViewManager(context); + guest_manager = + factory_->CreateGuestViewManager(context, delegate.Pass()); } else { - guest_manager = new GuestViewManager(context); + guest_manager = new GuestViewManager(context, delegate.Pass()); } context->SetUserData(guestview::kGuestViewManagerKeyName, guest_manager); } @@ -63,7 +60,7 @@ GuestViewManager* GuestViewManager::FromBrowserContext( } // static -GuestViewManager* GuestViewManager::FromBrowserContextIfAvailable( +GuestViewManager* GuestViewManager::FromBrowserContext( BrowserContext* context) { return static_cast<GuestViewManager*>(context->GetUserData( guestview::kGuestViewManagerKeyName)); @@ -122,6 +119,10 @@ void GuestViewManager::DetachGuest(GuestViewBase* guest) { instance_id_map_.erase(it); } +bool GuestViewManager::IsOwnedByExtension(GuestViewBase* guest) { + return delegate_->IsOwnedByExtension(guest); +} + int GuestViewManager::GetNextInstanceID() { return ++current_instance_id_; } @@ -260,39 +261,19 @@ GuestViewBase* GuestViewManager::CreateGuestInternal( return it->second.Run(owner_web_contents); } -// static void GuestViewManager::RegisterGuestViewTypes() { - RegisterGuestViewType<AppViewGuest>(); - RegisterGuestViewType<ExtensionOptionsGuest>(); - RegisterGuestViewType<ExtensionViewGuest>(); - RegisterGuestViewType<MimeHandlerViewGuest>(); - RegisterGuestViewType<SurfaceWorkerGuest>(); - RegisterGuestViewType<WebViewGuest>(); + delegate_->RegisterAdditionalGuestViewTypes(); +} + +bool GuestViewManager::IsGuestAvailableToContext(GuestViewBase* guest) { + return delegate_->IsGuestAvailableToContext(guest); } -bool GuestViewManager::IsGuestAvailableToContext( - GuestViewBase* guest, - std::string* owner_extension_id) { - const Feature* feature = - FeatureProvider::GetAPIFeature(guest->GetAPINamespace()); - CHECK(feature); - - ProcessMap* process_map = ProcessMap::Get(context_); - CHECK(process_map); - - const Extension* owner_extension = ProcessManager::Get(context_)-> - GetExtensionForWebContents(guest->owner_web_contents()); - *owner_extension_id = owner_extension ? owner_extension->id() : std::string(); - - // Ok for |owner_extension| to be nullptr, the embedder might be WebUI. - Feature::Availability availability = feature->IsAvailableToContext( - owner_extension, - process_map->GetMostLikelyContextType( - owner_extension, - guest->owner_web_contents()->GetRenderProcessHost()->GetID()), - guest->GetOwnerSiteURL()); - - return availability.is_available(); +void GuestViewManager::DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id) { + delegate_->DispatchEvent(event_name, args.Pass(), guest, instance_id); } content::WebContents* GuestViewManager::GetGuestByInstanceID( diff --git a/extensions/browser/guest_view/guest_view_manager.h b/extensions/browser/guest_view/guest_view_manager.h index 626b583..e1fb334 100644 --- a/extensions/browser/guest_view/guest_view_manager.h +++ b/extensions/browser/guest_view/guest_view_manager.h @@ -22,6 +22,10 @@ class BrowserContext; class WebContents; } // namespace content +namespace guestview { +class GuestViewManagerDelegate; +} // namespace guestview + namespace extensions{ class GuestViewBase; class GuestViewManagerFactory; @@ -29,17 +33,19 @@ class GuestViewManagerFactory; class GuestViewManager : public content::BrowserPluginGuestManager, public base::SupportsUserData::Data { public: - explicit GuestViewManager(content::BrowserContext* context); + GuestViewManager(content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate); ~GuestViewManager() override; // Returns the GuestViewManager associated with |context|. If one isn't // available, then it is created and returned. - static GuestViewManager* FromBrowserContext(content::BrowserContext* context); + static GuestViewManager* CreateWithDelegate( + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate); // Returns the GuestViewManager associated with |context|. If one isn't // available, then nullptr is returned. - static GuestViewManager* FromBrowserContextIfAvailable( - content::BrowserContext* context); + static GuestViewManager* FromBrowserContext(content::BrowserContext* context); // Overrides factory for testing. Default (NULL) value indicates regular // (non-test) environment. @@ -67,6 +73,9 @@ class GuestViewManager : public content::BrowserPluginGuestManager, // ID if one exists. void DetachGuest(GuestViewBase* guest); + // Indicates whether the |guest| is owned by an extension or Chrome App. + bool IsOwnedByExtension(GuestViewBase* guest); + int GetNextInstanceID(); int GetGuestInstanceIDForElementID( int owner_process_id, @@ -105,7 +114,7 @@ class GuestViewManager : public content::BrowserPluginGuestManager, protected: friend class GuestViewBase; - FRIEND_TEST_ALL_PREFIXES(GuestViewManagerTest, AddRemove); + friend class GuestViewEvent; // Can be overriden in tests. virtual void AddGuest(int guest_instance_id, @@ -123,8 +132,14 @@ class GuestViewManager : public content::BrowserPluginGuestManager, // Indicates whether the provided |guest| can be used in the context it has // been created. - bool IsGuestAvailableToContext(GuestViewBase* guest, - std::string* owner_extension_id); + bool IsGuestAvailableToContext(GuestViewBase* guest); + + // Dispatches the event with |name| with the provided |args| to the embedder + // of the given |guest| with |instance_id| for routing. + void DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id); content::WebContents* GetGuestByInstanceID(int guest_instance_id); @@ -189,6 +204,8 @@ class GuestViewManager : public content::BrowserPluginGuestManager, content::BrowserContext* context_; + scoped_ptr<guestview::GuestViewManagerDelegate> delegate_; + DISALLOW_COPY_AND_ASSIGN(GuestViewManager); }; diff --git a/extensions/browser/guest_view/guest_view_manager_delegate.h b/extensions/browser/guest_view/guest_view_manager_delegate.h new file mode 100644 index 0000000..f6e1795 --- /dev/null +++ b/extensions/browser/guest_view/guest_view_manager_delegate.h @@ -0,0 +1,53 @@ +// Copyright 2015 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 EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_MANAGER_DELEGATE_H_ +#define EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_MANAGER_DELEGATE_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" + +namespace base { +class DictionaryValue; +} // namespace base + +namespace extensions { +class GuestViewBase; +} // namespace extensions + +namespace guestview { + +// A GuestViewManagerDelegate interface allows GuestViewManager to delegate +// responsibilities to other modules in Chromium. Different builds of Chromium +// may use different GuestViewManagerDelegate implementations. For example, +// mobile builds of Chromium do not include an extensions module and so +// permission checks would be different, and IsOwnedByExtension would always +// return false. +class GuestViewManagerDelegate { + public: + virtual ~GuestViewManagerDelegate() {} + + // Dispatches the event with |name| with the provided |args| to the embedder + // of the given |guest| with |instance_id| for routing. + virtual void DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + extensions::GuestViewBase* guest, + int instance_id) = 0; + + // Indicates whether the |guest| can be used within the context of where it + // was created. + virtual bool IsGuestAvailableToContext(extensions::GuestViewBase* guest) = 0; + + // Indicates whether the |guest| is owned by an extension or Chrome App. + virtual bool IsOwnedByExtension(extensions::GuestViewBase* guest) = 0; + + // Registers additional GuestView types the delegator (GuestViewManger) can + // create. + virtual void RegisterAdditionalGuestViewTypes() = 0; +}; + +} // namespace guestview + +#endif // EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_MANAGER_DELEGATE_H_ diff --git a/extensions/browser/guest_view/guest_view_manager_factory.h b/extensions/browser/guest_view/guest_view_manager_factory.h index 9133734..695731c 100644 --- a/extensions/browser/guest_view/guest_view_manager_factory.h +++ b/extensions/browser/guest_view/guest_view_manager_factory.h @@ -9,6 +9,10 @@ namespace content { class BrowserContext; } +namespace guestview { +class GuestViewManagerDelegate; +} // namespace guestview + namespace extensions { class GuestViewManager; @@ -16,7 +20,8 @@ class GuestViewManager; class GuestViewManagerFactory { public: virtual GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) = 0; + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate) = 0; protected: virtual ~GuestViewManagerFactory() {} diff --git a/extensions/browser/guest_view/guest_view_manager_unittest.cc b/extensions/browser/guest_view/guest_view_manager_unittest.cc index 1646e49..2a380e4 100644 --- a/extensions/browser/guest_view/guest_view_manager_unittest.cc +++ b/extensions/browser/guest_view/guest_view_manager_unittest.cc @@ -9,36 +9,17 @@ #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/web_contents_tester.h" #include "extensions/browser/extensions_test.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" +#include "extensions/browser/guest_view/guest_view_manager.h" +#include "extensions/browser/guest_view/guest_view_manager_delegate.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" using content::WebContents; using content::WebContentsTester; +using guestview::GuestViewManagerDelegate; namespace extensions { -namespace guestview { - -// This class allows us to access some private variables in -// GuestViewManager. -class TestGuestViewManager : public GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) - : GuestViewManager(context) {} - - int last_instance_id_removed_for_testing() { - return last_instance_id_removed_; - } - - size_t GetRemovedInstanceIdSize() { return removed_instance_ids_.size(); } - - private: - using GuestViewManager::last_instance_id_removed_; - using GuestViewManager::removed_instance_ids_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManager); -}; - -} // namespace guestview - namespace { class GuestViewManagerTest : public extensions::ExtensionsTest { @@ -64,14 +45,16 @@ class GuestViewManagerTest : public extensions::ExtensionsTest { TEST_F(GuestViewManagerTest, AddRemove) { content::TestBrowserContext browser_context; - scoped_ptr<guestview::TestGuestViewManager> manager( - new guestview::TestGuestViewManager(&browser_context)); + scoped_ptr<GuestViewManagerDelegate> delegate( + new ExtensionsGuestViewManagerDelegate(&browser_context)); + scoped_ptr<TestGuestViewManager> manager( + new extensions::TestGuestViewManager(&browser_context, delegate.Pass())); scoped_ptr<WebContents> web_contents1(CreateWebContents()); scoped_ptr<WebContents> web_contents2(CreateWebContents()); scoped_ptr<WebContents> web_contents3(CreateWebContents()); - EXPECT_EQ(0, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(0, manager->last_instance_id_removed()); EXPECT_TRUE(manager->CanUseGuestInstanceID(1)); EXPECT_TRUE(manager->CanUseGuestInstanceID(2)); @@ -86,7 +69,7 @@ TEST_F(GuestViewManagerTest, AddRemove) { EXPECT_FALSE(manager->CanUseGuestInstanceID(2)); EXPECT_TRUE(manager->CanUseGuestInstanceID(3)); - EXPECT_EQ(0, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(0, manager->last_instance_id_removed()); EXPECT_TRUE(manager->CanUseGuestInstanceID(3)); @@ -95,15 +78,15 @@ TEST_F(GuestViewManagerTest, AddRemove) { EXPECT_FALSE(manager->CanUseGuestInstanceID(1)); EXPECT_FALSE(manager->CanUseGuestInstanceID(2)); - EXPECT_EQ(2, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(2, manager->last_instance_id_removed()); manager->RemoveGuest(3); - EXPECT_EQ(3, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(3, manager->last_instance_id_removed()); EXPECT_FALSE(manager->CanUseGuestInstanceID(1)); EXPECT_FALSE(manager->CanUseGuestInstanceID(2)); EXPECT_FALSE(manager->CanUseGuestInstanceID(3)); - EXPECT_EQ(0u, manager->GetRemovedInstanceIdSize()); + EXPECT_EQ(0, manager->GetNumRemovedInstanceIDs()); } } // namespace extensions diff --git a/extensions/browser/guest_view/guest_view_message_filter.cc b/extensions/browser/guest_view/guest_view_message_filter.cc index 3e833d5..26188fa 100644 --- a/extensions/browser/guest_view/guest_view_message_filter.cc +++ b/extensions/browser/guest_view/guest_view_message_filter.cc @@ -65,8 +65,7 @@ void GuestViewMessageFilter::OnAttachGuest( int guest_instance_id, const base::DictionaryValue& params) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - auto manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context_); + auto manager = GuestViewManager::FromBrowserContext(browser_context_); // We should have a GuestViewManager at this point. If we don't then the // embedder is misbehaving. if (!manager) diff --git a/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc b/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc index 2dffde3..6c30d9c 100644 --- a/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc +++ b/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc @@ -65,9 +65,8 @@ void SurfaceWorkerGuest::CreateWebContents( content::kGuestScheme, GetOwnerSiteURL().host().c_str())); - GuestViewManager* guest_view_manager = - GuestViewManager::FromBrowserContextIfAvailable( - owner_web_contents()->GetBrowserContext()); + GuestViewManager* guest_view_manager = GuestViewManager::FromBrowserContext( + owner_web_contents()->GetBrowserContext()); content::SiteInstance* guest_site_instance = guest_view_manager->GetGuestSiteInstance(guest_site); WebContents::CreateParams params( diff --git a/extensions/browser/guest_view/test_guest_view_manager.cc b/extensions/browser/guest_view/test_guest_view_manager.cc index ce7b125..9427d78 100644 --- a/extensions/browser/guest_view/test_guest_view_manager.cc +++ b/extensions/browser/guest_view/test_guest_view_manager.cc @@ -10,6 +10,7 @@ #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/extension_host.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/process_manager.h" #include "extensions/common/extension.h" #include "extensions/common/extension_paths.h" @@ -17,19 +18,28 @@ #include "extensions/shell/test/shell_test.h" #include "extensions/test/extension_test_message_listener.h" +using guestview::GuestViewManagerDelegate; + namespace extensions { -TestGuestViewManager::TestGuestViewManager(content::BrowserContext* context) - : GuestViewManager(context) { +TestGuestViewManager::TestGuestViewManager( + content::BrowserContext* context, + scoped_ptr<GuestViewManagerDelegate> delegate) + : GuestViewManager(context, delegate.Pass()), + num_guests_created_(0) { } TestGuestViewManager::~TestGuestViewManager() { } -int TestGuestViewManager::GetNumGuests() const { +int TestGuestViewManager::GetNumGuestsActive() const { return guest_web_contents_by_instance_id_.size(); } +int TestGuestViewManager::GetNumRemovedInstanceIDs() const { + return removed_instance_ids_.size(); +} + content::WebContents* TestGuestViewManager::GetLastGuestCreated() { content::WebContents* web_contents = nullptr; for (int i = current_instance_id_; i >= 0; i--) { @@ -53,8 +63,12 @@ void TestGuestViewManager::WaitForGuestCreated() { } content::WebContents* TestGuestViewManager::WaitForSingleGuestCreated() { - if (GetNumGuests() == 0) + if (!GetNumGuestsActive()) { + // Guests have been created and subsequently destroyed. + if (num_guests_created() > 0) + return nullptr; WaitForGuestCreated(); + } return GetLastGuestCreated(); } @@ -67,6 +81,8 @@ void TestGuestViewManager::AddGuest(int guest_instance_id, linked_ptr<content::WebContentsDestroyedWatcher>( new content::WebContentsDestroyedWatcher(guest_web_contents))); + ++num_guests_created_; + if (created_message_loop_runner_.get()) created_message_loop_runner_->Quit(); } @@ -84,17 +100,12 @@ TestGuestViewManagerFactory::~TestGuestViewManagerFactory() { } GuestViewManager* TestGuestViewManagerFactory::CreateGuestViewManager( - content::BrowserContext* context) { - return GetManager(context); -} - -// This function gets called from GuestViewManager::FromBrowserContext(), -// where test_guest_view_manager_ is assigned to a linked_ptr that takes care -// of deleting it. -TestGuestViewManager* TestGuestViewManagerFactory::GetManager( - content::BrowserContext* context) { - DCHECK(!test_guest_view_manager_); - test_guest_view_manager_ = new TestGuestViewManager(context); + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate) { + if (!test_guest_view_manager_) { + test_guest_view_manager_ = + new TestGuestViewManager(context, delegate.Pass()); + } return test_guest_view_manager_; } diff --git a/extensions/browser/guest_view/test_guest_view_manager.h b/extensions/browser/guest_view/test_guest_view_manager.h index b826f30..d819325 100644 --- a/extensions/browser/guest_view/test_guest_view_manager.h +++ b/extensions/browser/guest_view/test_guest_view_manager.h @@ -15,7 +15,9 @@ namespace extensions { class TestGuestViewManager : public GuestViewManager { public: - explicit TestGuestViewManager(content::BrowserContext* context); + TestGuestViewManager( + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate); ~TestGuestViewManager() override; void WaitForAllGuestsDeleted(); @@ -23,15 +25,35 @@ class TestGuestViewManager : public GuestViewManager { content::WebContents* GetLastGuestCreated(); + // Returns the number of guests currently still alive at the time of calling + // this method. + int GetNumGuestsActive() const; + + // Returns the size of the set of removed instance IDs. + int GetNumRemovedInstanceIDs() const; + + // Returns the number of guests that have been created since the creation of + // this GuestViewManager. + int num_guests_created() const { return num_guests_created_; } + + // Returns the last guest instance ID removed from the manager. + int last_instance_id_removed() const { return last_instance_id_removed_; } + private: + FRIEND_TEST_ALL_PREFIXES(GuestViewManagerTest, AddRemove); + // GuestViewManager override: void AddGuest(int guest_instance_id, content::WebContents* guest_web_contents) override; void RemoveGuest(int guest_instance_id) override; - int GetNumGuests() const; void WaitForGuestCreated(); + using GuestViewManager::last_instance_id_removed_; + using GuestViewManager::removed_instance_ids_; + + int num_guests_created_; + std::vector<linked_ptr<content::WebContentsDestroyedWatcher>> guest_web_contents_watchers_; scoped_refptr<content::MessageLoopRunner> created_message_loop_runner_; @@ -46,9 +68,8 @@ class TestGuestViewManagerFactory : public GuestViewManagerFactory { ~TestGuestViewManagerFactory() override; GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override; - - TestGuestViewManager* GetManager(content::BrowserContext* context); + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate) override; private: TestGuestViewManager* test_guest_view_manager_; diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc index 61b87bd..f432276 100644 --- a/extensions/browser/guest_view/web_view/web_view_apitest.cc +++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc @@ -17,6 +17,7 @@ #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/extension_host.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" #include "extensions/browser/guest_view/test_guest_view_manager.h" @@ -237,9 +238,20 @@ content::WebContents* WebViewAPITest::GetEmbedderWebContents() { } TestGuestViewManager* WebViewAPITest::GetGuestViewManager() { - return static_cast<TestGuestViewManager*>( - TestGuestViewManager::FromBrowserContext( - ShellContentBrowserClient::Get()->GetBrowserContext())); + content::BrowserContext* context = + ShellContentBrowserClient::Get()->GetBrowserContext(); + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(context)); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + context, + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate(context)))); + } + return manager; } void WebViewAPITest::SendMessageToGuestAndWait( diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index ba6cb76..f29e12f 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc @@ -284,7 +284,7 @@ void WebViewGuest::CreateWebContents( // 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. - auto guest_view_manager = GuestViewManager::FromBrowserContextIfAvailable( + auto guest_view_manager = GuestViewManager::FromBrowserContext( owner_render_process_host->GetBrowserContext()); content::SiteInstance* guest_site_instance = guest_view_manager->GetGuestSiteInstance(guest_site); @@ -395,7 +395,7 @@ void WebViewGuest::EmbedderWillBeDestroyed() { base::Bind( &RemoveWebViewEventListenersOnIOThread, browser_context(), - owner_extension_id(), + owner_host(), owner_web_contents()->GetRenderProcessHost()->GetID(), view_instance_id())); } @@ -562,7 +562,7 @@ void WebViewGuest::LoadAbort(bool is_top_level, void WebViewGuest::CreateNewGuestWebViewWindow( const content::OpenURLParams& params) { GuestViewManager* guest_manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context()); + GuestViewManager::FromBrowserContext(browser_context()); // Set the attach params to use the same partition as the opener. // We pull the partition information from the site's URL, which is of the // form guest://site/{persist}?{partition_name}. @@ -871,7 +871,7 @@ void WebViewGuest::PushWebViewStateToIOThread() { owner_web_contents()->GetRenderProcessHost()->GetID(); web_view_info.instance_id = view_instance_id(); web_view_info.partition_id = partition_id; - web_view_info.owner_extension_id = owner_extension_id(); + web_view_info.owner_host = owner_host(); web_view_info.rules_registry_id = rules_registry_id_; // Get content scripts IDs added by the guest. @@ -971,8 +971,10 @@ void WebViewGuest::NavigateGuest(const std::string& src, bool WebViewGuest::HandleKeyboardShortcuts( const content::NativeWebKeyboardEvent& event) { // <webview> outside of Chrome Apps do not handle keyboard shortcuts. - if (!in_extension()) + if (!GuestViewManager::FromBrowserContext(browser_context())-> + IsOwnedByExtension(this)) { return false; + } if (event.type != blink::WebInputEvent::RawKeyDown) return false; @@ -1360,12 +1362,14 @@ void WebViewGuest::RequestNewWindowPermission( } GURL WebViewGuest::ResolveURL(const std::string& src) { - if (!in_extension()) + if (!GuestViewManager::FromBrowserContext(browser_context())-> + IsOwnedByExtension(this)) { return GURL(src); + } GURL default_url(base::StringPrintf("%s://%s/", kExtensionScheme, - owner_extension_id().c_str())); + owner_host().c_str())); return default_url.Resolve(src); } diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc index feed6b3..3068ae3 100644 --- a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc +++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc @@ -81,7 +81,7 @@ bool WebViewRendererState::GetInfo(int guest_process_id, bool WebViewRendererState::GetOwnerInfo(int guest_process_id, int* owner_process_id, - std::string* owner_extension_id) const { + std::string* owner_host) const { DCHECK_CURRENTLY_ON(BrowserThread::IO); // TODO(fsamuel): Store per-process info in WebViewPartitionInfo instead of in // WebViewInfo. @@ -89,8 +89,8 @@ bool WebViewRendererState::GetOwnerInfo(int guest_process_id, if (info.first.first == guest_process_id) { if (owner_process_id) *owner_process_id = info.second.embedder_process_id; - if (owner_extension_id) - *owner_extension_id = info.second.owner_extension_id; + if (owner_host) + *owner_host = info.second.owner_host; return true; } } diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.h b/extensions/browser/guest_view/web_view/web_view_renderer_state.h index 42b886f..b6be959 100644 --- a/extensions/browser/guest_view/web_view/web_view_renderer_state.h +++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.h @@ -25,7 +25,7 @@ class WebViewRendererState { int instance_id; int rules_registry_id; std::string partition_id; - std::string owner_extension_id; + std::string owner_host; std::set<int> content_script_ids; WebViewInfo(); @@ -43,7 +43,7 @@ class WebViewRendererState { // <webview>. Called on the IO thread. bool GetOwnerInfo(int guest_process_id, int* owner_process_id, - std::string* owner_extension_id) const; + std::string* owner_host) const; // Looks up the partition info for the embedder <webview> for a given guest // process. Called on the IO thread. diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi index 7963043..05a474d 100644 --- a/extensions/extensions.gypi +++ b/extensions/extensions.gypi @@ -637,6 +637,8 @@ 'browser/guest_view/extension_view/extension_view_guest.h', 'browser/guest_view/extension_view/extension_view_guest_delegate.cc', 'browser/guest_view/extension_view/extension_view_guest_delegate.h', + 'browser/guest_view/extensions_guest_view_manager_delegate.cc', + 'browser/guest_view/extensions_guest_view_manager_delegate.h', 'browser/guest_view/extensions_guest_view_message_filter.cc', 'browser/guest_view/extensions_guest_view_message_filter.h', 'browser/guest_view/guest_view.h', @@ -646,6 +648,7 @@ 'browser/guest_view/guest_view_event.h', 'browser/guest_view/guest_view_manager.cc', 'browser/guest_view/guest_view_manager.h', + 'browser/guest_view/guest_view_manager_delegate.h', 'browser/guest_view/guest_view_manager_factory.h', 'browser/guest_view/guest_view_message_filter.cc', 'browser/guest_view/guest_view_message_filter.h', diff --git a/extensions/shell/browser/shell_browser_context.cc b/extensions/shell/browser/shell_browser_context.cc index 61aec77..827eabe 100644 --- a/extensions/shell/browser/shell_browser_context.cc +++ b/extensions/shell/browser/shell_browser_context.cc @@ -35,7 +35,7 @@ ShellBrowserContext::~ShellBrowserContext() { } content::BrowserPluginGuestManager* ShellBrowserContext::GetGuestManager() { - return GuestViewManager::FromBrowserContextIfAvailable(this); + return GuestViewManager::FromBrowserContext(this); } storage::SpecialStoragePolicy* ShellBrowserContext::GetSpecialStoragePolicy() { |