summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-10 03:45:08 +0000
committerbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-10 03:45:08 +0000
commitd72d3a6b57d88fe88d3db71dd17239166a1c59ff (patch)
tree6839eb3eb47e530f28f617c48d7bec2b3f72de82
parent325940225f8caffea733f85f209db0ef12d6c0fb (diff)
downloadchromium_src-d72d3a6b57d88fe88d3db71dd17239166a1c59ff.zip
chromium_src-d72d3a6b57d88fe88d3db71dd17239166a1c59ff.tar.gz
chromium_src-d72d3a6b57d88fe88d3db71dd17239166a1c59ff.tar.bz2
Pull shell window stuff out of ExtensionHost and put in ShellWindow
This will let us iterate quicker on ShellWindow and platform apps and let them do things (like have TabContentsWrappers) that normal ExtensionHost windows shouldn't do. BUG=None TEST=Platform apps still work, browser tests. Review URL: https://chromiumcodereview.appspot.com/10119003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136239 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc10
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.h4
-rw-r--r--chrome/browser/extensions/extension_host.cc30
-rw-r--r--chrome/browser/extensions/extension_host.h4
-rw-r--r--chrome/browser/extensions/extension_process_manager.cc51
-rw-r--r--chrome/browser/extensions/extension_process_manager.h11
-rw-r--r--chrome/browser/extensions/platform_app_browsertest.cc57
-rw-r--r--chrome/browser/extensions/shell_window_registry.cc59
-rw-r--r--chrome/browser/extensions/shell_window_registry.h65
-rw-r--r--chrome/browser/task_manager/task_manager_resource_providers.cc44
-rw-r--r--chrome/browser/task_manager/task_manager_resource_providers.h1
-rw-r--r--chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h6
-rw-r--r--chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm20
-rw-r--r--chrome/browser/ui/extensions/shell_window.cc134
-rw-r--r--chrome/browser/ui/extensions/shell_window.h68
-rw-r--r--chrome/browser/ui/gtk/extensions/shell_window_gtk.cc23
-rw-r--r--chrome/browser/ui/gtk/extensions/shell_window_gtk.h6
-rw-r--r--chrome/browser/ui/views/extensions/shell_window_views.cc89
-rw-r--r--chrome/browser/ui/views/extensions/shell_window_views.h28
-rw-r--r--chrome/chrome_browser_extensions.gypi2
-rw-r--r--chrome/common/chrome_notification_types.h8
21 files changed, 493 insertions, 227 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index f86d997..113fcbf 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -94,6 +94,16 @@ base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER;
} // namespace
+ExtensionWindowController*
+ ExtensionFunctionDispatcher::Delegate::GetExtensionWindowController()
+ const {
+ return NULL;
+}
+
+content::WebContents*
+ ExtensionFunctionDispatcher::Delegate::GetAssociatedWebContents() const {
+ return NULL;
+}
void ExtensionFunctionDispatcher::GetAllFunctionNames(
std::vector<std::string>* names) {
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h
index 4a731d9..5278171 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.h
+++ b/chrome/browser/extensions/extension_function_dispatcher.h
@@ -55,13 +55,13 @@ class ExtensionFunctionDispatcher
public:
// Returns the ExtensionWindowController associated with this delegate,
// or NULL if no window is associated with the delegate.
- virtual ExtensionWindowController* GetExtensionWindowController() const = 0;
+ virtual ExtensionWindowController* GetExtensionWindowController() const;
// Asks the delegate for any relevant WebContents associated with this
// context. For example, the WebbContents in which an infobar or
// chrome-extension://<id> URL are being shown. Callers must check for a
// NULL return value (as in the case of a background page).
- virtual content::WebContents* GetAssociatedWebContents() const = 0;
+ virtual content::WebContents* GetAssociatedWebContents() const;
protected:
virtual ~Delegate() {}
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 71f3281..e7562fc 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -179,10 +179,6 @@ void ExtensionHost::CreateView(Browser* browser) {
#endif
}
-void ExtensionHost::CreateViewWithoutBrowser() {
- CreateView(NULL);
-}
-
WebContents* ExtensionHost::GetAssociatedWebContents() const {
return associated_web_contents_;
}
@@ -196,7 +192,6 @@ void ExtensionHost::SetAssociatedWebContents(
}
}
-
content::RenderProcessHost* ExtensionHost::render_process_host() const {
return render_view_host()->GetProcess();
}
@@ -211,13 +206,10 @@ bool ExtensionHost::IsRenderViewLive() const {
}
void ExtensionHost::CreateRenderViewSoon() {
- if ((render_process_host() && render_process_host()->HasConnection()) ||
- extension_host_type_ == chrome::VIEW_TYPE_APP_SHELL) {
+ if ((render_process_host() && render_process_host()->HasConnection())) {
// If the process is already started, go ahead and initialize the RenderView
// synchronously. The process creation is the real meaty part that we want
// to defer.
- // We also skip the ratelimiting in the shell window case. This is a hack
- // (see crbug.com/124350 for details).
CreateRenderViewNow();
} else {
ProcessCreationQueue::GetInstance()->CreateSoon(this);
@@ -295,8 +287,8 @@ void ExtensionHost::Observe(int type,
void ExtensionHost::ResizeDueToAutoResize(WebContents* source,
const gfx::Size& new_size) {
- if (view_.get())
- view_->ResizeDueToAutoResize(new_size);
+ if (view())
+ view()->ResizeDueToAutoResize(new_size);
}
void ExtensionHost::RenderViewGone(base::TerminationStatus status) {
@@ -340,11 +332,10 @@ void ExtensionHost::DidStopLoading() {
if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP ||
extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG ||
extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR ||
- extension_host_type_ == chrome::VIEW_TYPE_APP_SHELL ||
extension_host_type_ == chrome::VIEW_TYPE_PANEL) {
#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
- if (view_.get())
- view_->DidStopLoading();
+ if (view())
+ view()->DidStopLoading();
#endif
}
if (notify) {
@@ -360,8 +351,6 @@ void ExtensionHost::DidStopLoading() {
} else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) {
UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime",
since_created_.Elapsed());
- } else if (extension_host_type_ == chrome::VIEW_TYPE_APP_SHELL) {
- UMA_HISTOGRAM_TIMES("Extensions.ShellLoadTime", since_created_.Elapsed());
} else if (extension_host_type_ == chrome::VIEW_TYPE_PANEL) {
UMA_HISTOGRAM_TIMES("Extensions.PanelLoadTime", since_created_.Elapsed());
}
@@ -401,16 +390,11 @@ void ExtensionHost::CloseContents(WebContents* contents) {
extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG ||
extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE ||
extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR ||
- extension_host_type_ == chrome::VIEW_TYPE_APP_SHELL ||
extension_host_type_ == chrome::VIEW_TYPE_PANEL) {
Close();
}
}
-bool ExtensionHost::ShouldSuppressDialogs() {
- return extension_->is_platform_app();
-}
-
void ExtensionHost::WillRunJavaScriptDialog() {
ExtensionProcessManager* pm =
ExtensionSystem::Get(profile_)->process_manager();
@@ -510,8 +494,8 @@ void ExtensionHost::OnDecrementLazyKeepaliveCount() {
void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) {
render_view_host_ = render_view_host;
- if (view_.get())
- view_->RenderViewCreated();
+ if (view())
+ view()->RenderViewCreated();
// If the host is bound to a window, then extract its id. Extensions hosted
// in ExternalTabContainer objects may not have an associated window.
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 764f05b..96aa74d 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -92,9 +92,6 @@ class ExtensionHost : public content::WebContentsDelegate,
// instantiate Browser objects.
void CreateView(Browser* browser);
- // Helper variant of the above for cases where no Browser is present.
- void CreateViewWithoutBrowser();
-
const Extension* extension() const { return extension_; }
const std::string& extension_id() const { return extension_id_; }
content::WebContents* host_contents() const { return host_contents_.get(); }
@@ -162,7 +159,6 @@ class ExtensionHost : public content::WebContentsDelegate,
const gfx::Rect& initial_pos,
bool user_gesture) OVERRIDE;
virtual void CloseContents(content::WebContents* contents) OVERRIDE;
- virtual bool ShouldSuppressDialogs() OVERRIDE;
// content::NotificationObserver
virtual void Observe(int type,
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
index 8b606e7..9bc68d6 100644
--- a/chrome/browser/extensions/extension_process_manager.cc
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -170,22 +170,6 @@ ExtensionProcessManager::~ExtensionProcessManager() {
DCHECK(background_hosts_.empty());
}
-ExtensionHost* ExtensionProcessManager::CreateShellHost(
- const Extension* extension,
- const GURL& url) {
- DCHECK(extension);
- ExtensionHost* host = new ExtensionHost(extension,
- GetSiteInstanceForURL(url),
- url,
- chrome::VIEW_TYPE_APP_SHELL);
- host->CreateViewWithoutBrowser();
- content::WebContents* host_contents = host->host_contents();
- host_contents->GetMutableRendererPrefs()->browser_handles_all_requests = true;
- host_contents->GetRenderViewHost()->SyncRendererPrefs();
- OnExtensionHostCreated(host, false /* not a background host */);
- return host;
-}
-
void ExtensionProcessManager::EnsureBrowserWhenRequired(
Browser* browser,
content::ViewType view_type) {
@@ -361,6 +345,11 @@ void ExtensionProcessManager::UnregisterRenderViewHost(
if (view == all_extension_views_.end())
return;
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
+ content::Source<Profile>(GetProfile()),
+ content::Details<RenderViewHost>(render_view_host));
+
content::ViewType view_type = view->second;
all_extension_views_.erase(view);
@@ -381,18 +370,17 @@ void ExtensionProcessManager::UpdateRegisteredRenderView(
if (view == all_extension_views_.end())
return;
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
+ content::Source<Profile>(GetProfile()),
+ content::Details<RenderViewHost>(render_view_host));
+
view->second = render_view_host->GetDelegate()->GetRenderViewType();
// Keep the lazy background page alive as long as any non-background-page
// extension views are visible. Keepalive count balanced in
// UnregisterRenderViewHost.
- if (view->second != content::VIEW_TYPE_INVALID &&
- view->second != chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
- const Extension* extension = GetExtensionForRenderViewHost(
- render_view_host);
- if (extension)
- IncrementLazyKeepaliveCount(extension);
- }
+ IncrementLazyKeepaliveCountForView(render_view_host);
}
SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL(const GURL& url) {
@@ -442,6 +430,18 @@ int ExtensionProcessManager::DecrementLazyKeepaliveCount(
return count;
}
+void ExtensionProcessManager::IncrementLazyKeepaliveCountForView(
+ RenderViewHost* render_view_host) {
+ content::ViewType view_type =
+ render_view_host->GetDelegate()->GetRenderViewType();
+ if (view_type != content::VIEW_TYPE_INVALID &&
+ view_type != chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
+ const Extension* extension = GetExtensionForRenderViewHost(
+ render_view_host);
+ if (extension)
+ IncrementLazyKeepaliveCount(extension);
+ }
+}
void ExtensionProcessManager::OnLazyBackgroundPageIdle(
const std::string& extension_id, int sequence_id) {
@@ -552,7 +552,6 @@ void ExtensionProcessManager::Observe(
ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
if (background_hosts_.erase(host))
ClearBackgroundPageData(host->extension()->id());
- platform_app_hosts_.erase(host);
break;
}
@@ -623,8 +622,6 @@ void ExtensionProcessManager::OnExtensionHostCreated(ExtensionHost* host,
DCHECK_EQ(site_instance_->GetBrowserContext(), host->profile());
if (is_background)
background_hosts_.insert(host);
- if (host->extension()->is_platform_app())
- platform_app_hosts_.insert(host);
}
void ExtensionProcessManager::CloseBackgroundHost(ExtensionHost* host) {
@@ -653,7 +650,7 @@ void ExtensionProcessManager::ClearBackgroundPageData(
for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin();
it != all_extension_views_.end(); ++it) {
if (GetExtensionID(it->first) == extension_id)
- UpdateRegisteredRenderView(it->first);
+ IncrementLazyKeepaliveCountForView(it->first);
}
}
diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h
index adaa7fd..33f5820 100644
--- a/chrome/browser/extensions/extension_process_manager.h
+++ b/chrome/browser/extensions/extension_process_manager.h
@@ -44,10 +44,6 @@ class ExtensionProcessManager : public content::NotificationObserver {
return background_hosts_;
}
- const ExtensionHostSet& platform_app_hosts() const {
- return platform_app_hosts_;
- }
-
typedef std::set<content::RenderViewHost*> ViewSet;
const ViewSet GetAllViews() const;
@@ -71,7 +67,6 @@ class ExtensionProcessManager : public content::NotificationObserver {
Browser* browser);
ExtensionHost* CreateInfobarHost(const GURL& url,
Browser* browser);
- ExtensionHost* CreateShellHost(const Extension* extension, const GURL& url);
// Open the extension's options page.
void OpenOptionsPage(const Extension* extension, Browser* browser);
@@ -119,6 +114,9 @@ class ExtensionProcessManager : public content::NotificationObserver {
int IncrementLazyKeepaliveCount(const Extension* extension);
int DecrementLazyKeepaliveCount(const Extension* extension);
+ void IncrementLazyKeepaliveCountForView(
+ content::RenderViewHost* render_view_host);
+
// Handles a response to the ShouldUnload message, used for lazy background
// pages.
void OnShouldUnloadAck(const std::string& extension_id, int sequence_id);
@@ -154,9 +152,6 @@ class ExtensionProcessManager : public content::NotificationObserver {
// The set of ExtensionHosts running viewless background extensions.
ExtensionHostSet background_hosts_;
- // The set of ExtensionHosts running platform apps.
- ExtensionHostSet platform_app_hosts_;
-
// A SiteInstance related to the SiteInstance for all extensions in
// this profile. We create it in such a way that a new
// browsing instance is created. This controls process grouping.
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc
index a4ade53..44f615a 100644
--- a/chrome/browser/extensions/platform_app_browsertest.cc
+++ b/chrome/browser/extensions/platform_app_browsertest.cc
@@ -8,15 +8,15 @@
#include "chrome/browser/automation/automation_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_browsertest.h"
-#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/render_view_context_menu.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/chrome_view_type.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"
@@ -57,7 +57,6 @@ class PlatformAppBrowserTest : public ExtensionApiTest {
protected:
void LoadAndLaunchPlatformApp(const char* name) {
- size_t platform_app_count = GetPlatformAppCount();
ui_test_utils::WindowedNotificationObserver app_loaded_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
@@ -78,41 +77,19 @@ class PlatformAppBrowserTest : public ExtensionApiTest {
NEW_WINDOW);
app_loaded_observer.Wait();
-
- // Now we have a new platform app running.
- EXPECT_EQ(platform_app_count + 1, GetPlatformAppCount());
- }
-
- // Gets the number of platform apps extension hosts that are running.
- size_t GetPlatformAppCount() {
- int count = 0;
- ExtensionProcessManager* process_manager =
- browser()->profile()->GetExtensionProcessManager();
- ExtensionProcessManager::const_iterator iter;
- ExtensionProcessManager::ExtensionHostSet platform_app_hosts =
- process_manager->platform_app_hosts();
- for (iter = platform_app_hosts.begin(); iter != platform_app_hosts.end();
- ++iter) {
- if ((*iter)->extension())
- count++;
- }
-
- return count;
}
- // Gets the WebContents associated with the ExtensionHost of the first
- // platform app shell window that is found (most tests only deal with one
- // platform app window, so this is good enough).
- WebContents* GetFirstPlatformAppShellWindowWebContents() {
- ExtensionProcessManager* process_manager =
- browser()->profile()->GetExtensionProcessManager();
- ExtensionProcessManager::const_iterator iter;
- ExtensionProcessManager::ExtensionHostSet platform_app_hosts =
- process_manager->platform_app_hosts();
- for (iter = platform_app_hosts.begin(); iter != platform_app_hosts.end();
- ++iter) {
- if ((*iter)->extension_host_type() == chrome::VIEW_TYPE_APP_SHELL)
- return (*iter)->host_contents();
+ // Gets the WebContents associated with the first shell window that is found
+ // (most tests only deal with one platform app window, so this is good
+ // enough).
+ WebContents* GetFirstShellWindowWebContents() {
+ ShellWindowRegistry* app_registry =
+ ShellWindowRegistry::Get(browser()->profile());
+ ShellWindowRegistry::const_iterator iter;
+ ShellWindowRegistry::ShellWindowSet shell_windows =
+ app_registry->shell_windows();
+ for (iter = shell_windows.begin(); iter != shell_windows.end(); ++iter) {
+ return (*iter)->web_contents();
}
return NULL;
@@ -132,13 +109,15 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, EmptyContextMenu) {
// The empty app doesn't add any context menu items, so its menu should
// only include the developer tools.
- WebContents* web_contents = GetFirstPlatformAppShellWindowWebContents();
+ WebContents* web_contents = GetFirstShellWindowWebContents();
ASSERT_TRUE(web_contents);
WebKit::WebContextMenuData data;
content::ContextMenuParams params(data);
PlatformAppContextMenu* menu = new PlatformAppContextMenu(web_contents,
params);
menu->Init();
+ // TODO(benwells): Remove the constant below. Instead of checking the
+ // number of menu items check certain item's absense and presence.
// 3 including separator
ASSERT_EQ(3, menu->menu_model().GetItemCount());
}
@@ -153,13 +132,15 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenu) {
// The context_menu app has one context menu item. This, along with a
// separator and the developer tools, is all that should be in the menu.
- WebContents* web_contents = GetFirstPlatformAppShellWindowWebContents();
+ WebContents* web_contents = GetFirstShellWindowWebContents();
ASSERT_TRUE(web_contents);
WebKit::WebContextMenuData data;
content::ContextMenuParams params(data);
PlatformAppContextMenu* menu = new PlatformAppContextMenu(web_contents,
params);
menu->Init();
+ // TODO(benwells): Remove the constant below. Instead of checking the
+ // number of menu items check certain item's absense and presence.
ASSERT_EQ(4, menu->menu_model().GetItemCount());
}
diff --git a/chrome/browser/extensions/shell_window_registry.cc b/chrome/browser/extensions/shell_window_registry.cc
new file mode 100644
index 0000000..375fb9c
--- /dev/null
+++ b/chrome/browser/extensions/shell_window_registry.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/shell_window_registry.h"
+#include "chrome/browser/profiles/profile_dependency_manager.h"
+
+ShellWindowRegistry::ShellWindowRegistry() {}
+
+ShellWindowRegistry::~ShellWindowRegistry() {}
+
+// static
+ShellWindowRegistry* ShellWindowRegistry::Get(Profile* profile) {
+ return Factory::GetForProfile(profile);
+}
+
+void ShellWindowRegistry::AddShellWindow(ShellWindow* shell_window) {
+ shell_windows_.insert(shell_window);
+}
+
+void ShellWindowRegistry::RemoveShellWindow(ShellWindow* shell_window) {
+ shell_windows_.erase(shell_window);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Factory boilerplate
+
+// static
+ShellWindowRegistry* ShellWindowRegistry::Factory::GetForProfile(
+ Profile* profile) {
+ return static_cast<ShellWindowRegistry*>(
+ GetInstance()->GetServiceForProfile(profile, true));
+}
+
+ShellWindowRegistry::Factory* ShellWindowRegistry::Factory::GetInstance() {
+ return Singleton<ShellWindowRegistry::Factory>::get();
+}
+
+ShellWindowRegistry::Factory::Factory()
+ : ProfileKeyedServiceFactory("ShellWindowRegistry",
+ ProfileDependencyManager::GetInstance()) {
+}
+
+ShellWindowRegistry::Factory::~Factory() {
+}
+
+ProfileKeyedService* ShellWindowRegistry::Factory::BuildServiceInstanceFor(
+ Profile* profile) const {
+ return new ShellWindowRegistry();
+}
+
+bool ShellWindowRegistry::Factory::ServiceIsCreatedWithProfile() {
+ return true;
+}
+
+bool ShellWindowRegistry::Factory::ServiceIsNULLWhileTesting() {
+ return false;
+}
diff --git a/chrome/browser/extensions/shell_window_registry.h b/chrome/browser/extensions/shell_window_registry.h
new file mode 100644
index 0000000..a2c5a4e
--- /dev/null
+++ b/chrome/browser/extensions/shell_window_registry.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
+#define CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
+#pragma once
+
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+
+class Profile;
+class ShellWindow;
+
+// The ShellWindowRegistry tracks the ShellWindows for all platform apps for a
+// particular profile.
+// This class is planned to evolve into tracking all PlatformApps for a
+// particular profile, with a PlatformApp encapsulating all views (background
+// page, shell windows, tray view, panels etc.) and other app level behaviour
+// (e.g. notifications the app is interested in, lifetime of the background
+// page).
+class ShellWindowRegistry : public ProfileKeyedService {
+ public:
+ typedef std::set<ShellWindow*> ShellWindowSet;
+ typedef ShellWindowSet::const_iterator const_iterator;
+
+ ShellWindowRegistry();
+ virtual ~ShellWindowRegistry();
+
+ // Returns the instance for the given profile, or NULL if none. This is
+ // a convenience wrapper around ShellWindowRegistryFactory::GetForProfile.
+ static ShellWindowRegistry* Get(Profile* profile);
+
+ void AddShellWindow(ShellWindow* shell_window);
+ void RemoveShellWindow(ShellWindow* shell_window);
+
+ const ShellWindowSet& shell_windows() const { return shell_windows_; }
+
+ private:
+ class Factory : public ProfileKeyedServiceFactory {
+ public:
+ static ShellWindowRegistry* GetForProfile(Profile* profile);
+
+ static Factory* GetInstance();
+ private:
+ friend struct DefaultSingletonTraits<Factory>;
+
+ Factory();
+ virtual ~Factory();
+
+ // ProfileKeyedServiceFactory
+ virtual ProfileKeyedService* BuildServiceInstanceFor(
+ Profile* profile) const OVERRIDE;
+ virtual bool ServiceIsCreatedWithProfile() OVERRIDE;
+ virtual bool ServiceIsNULLWhileTesting() OVERRIDE;
+ };
+
+ ShellWindowSet shell_windows_;
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc
index 327ea9a..b252812 100644
--- a/chrome/browser/task_manager/task_manager_resource_providers.cc
+++ b/chrome/browser/task_manager/task_manager_resource_providers.cc
@@ -1259,28 +1259,17 @@ void TaskManagerExtensionProcessResourceProvider::StartUpdating() {
if (!rvh->IsRenderViewLive())
continue;
- // Don't add WebContents (those are handled by
- // TaskManagerTabContentsResourceProvider) or background contents
- // (handled by TaskManagerBackgroundResourceProvider).
- // TODO(benwells): create specific chrome::VIEW_TYPE_TAB_CONTENTS for
- // tab contents, as VIEW_TYPE_WEB_CONTENTS is the default.
- content::ViewType view_type = rvh->GetDelegate()->GetRenderViewType();
- if (view_type == content::VIEW_TYPE_WEB_CONTENTS ||
- view_type == chrome::VIEW_TYPE_BACKGROUND_CONTENTS) {
- continue;
- }
-
AddToTaskManager(rvh);
}
}
}
// Register for notifications about extension process changes.
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_CREATED,
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
content::NotificationService::AllBrowserContextsAndSources());
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
content::NotificationService::AllBrowserContextsAndSources());
}
@@ -1290,13 +1279,13 @@ void TaskManagerExtensionProcessResourceProvider::StopUpdating() {
// Unregister for notifications about extension process changes.
registrar_.Remove(
- this, chrome::NOTIFICATION_EXTENSION_HOST_CREATED,
+ this, chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Remove(
this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Remove(
- this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+ this, chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
content::NotificationService::AllBrowserContextsAndSources());
// Delete all the resources.
@@ -1311,23 +1300,42 @@ void TaskManagerExtensionProcessResourceProvider::Observe(
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
- case chrome::NOTIFICATION_EXTENSION_HOST_CREATED:
+ case chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED:
AddToTaskManager(
- content::Details<ExtensionHost>(details).ptr()->render_view_host());
+ content::Details<content::RenderViewHost>(details).ptr());
break;
case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED:
- case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED:
RemoveFromTaskManager(
content::Details<ExtensionHost>(details).ptr()->render_view_host());
break;
+ case chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED:
+ RemoveFromTaskManager(
+ content::Details<content::RenderViewHost>(details).ptr());
+ break;
default:
NOTREACHED() << "Unexpected notification.";
return;
}
}
+bool TaskManagerExtensionProcessResourceProvider::
+ IsHandledByThisProvider(content::RenderViewHost* render_view_host) {
+ // Don't add WebContents (those are handled by
+ // TaskManagerTabContentsResourceProvider) or background contents (handled
+ // by TaskManagerBackgroundResourceProvider).
+ // TODO(benwells): create specific chrome::VIEW_TYPE_TAB_CONTENTS for
+ // tab contents, as VIEW_TYPE_WEB_CONTENTS is the default.
+ content::ViewType view_type =
+ render_view_host->GetDelegate()->GetRenderViewType();
+ return (view_type != content::VIEW_TYPE_WEB_CONTENTS &&
+ view_type != chrome::VIEW_TYPE_BACKGROUND_CONTENTS);
+}
+
void TaskManagerExtensionProcessResourceProvider::AddToTaskManager(
content::RenderViewHost* render_view_host) {
+ if (!IsHandledByThisProvider(render_view_host))
+ return;
+
TaskManagerExtensionProcessResource* resource =
new TaskManagerExtensionProcessResource(render_view_host);
DCHECK(resources_.find(render_view_host) == resources_.end());
diff --git a/chrome/browser/task_manager/task_manager_resource_providers.h b/chrome/browser/task_manager/task_manager_resource_providers.h
index e3299e9..721e3ec 100644
--- a/chrome/browser/task_manager/task_manager_resource_providers.h
+++ b/chrome/browser/task_manager/task_manager_resource_providers.h
@@ -402,6 +402,7 @@ class TaskManagerExtensionProcessResourceProvider
private:
virtual ~TaskManagerExtensionProcessResourceProvider();
+ bool IsHandledByThisProvider(content::RenderViewHost* render_view_host);
void AddToTaskManager(content::RenderViewHost* render_view_host);
void RemoveFromTaskManager(content::RenderViewHost* render_view_host);
diff --git a/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h b/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h
index d4d0f69..b5020ec 100644
--- a/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h
@@ -13,7 +13,7 @@
#include "chrome/browser/ui/extensions/shell_window.h"
#include "ui/gfx/rect.h"
-class ExtensionHost;
+class Profile;
class ShellWindowCocoa;
// A window controller for a minimal window to host a web app view. Passes
@@ -30,7 +30,9 @@ class ShellWindowCocoa;
// Cocoa bridge to ShellWindow.
class ShellWindowCocoa : public ShellWindow {
public:
- explicit ShellWindowCocoa(ExtensionHost* host);
+ ShellWindowCocoa(Profile* profile,
+ const Extension* extension,
+ const GURL& url);
// BaseWindow implementation.
virtual bool IsActive() const OVERRIDE;
diff --git a/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm b/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm
index 9487eab..01e41fb 100644
--- a/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm
@@ -5,10 +5,12 @@
#include "chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h"
#include "base/sys_string_conversions.h"
-#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/cocoa/browser_window_utils.h"
#include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h"
#include "chrome/common/extensions/extension.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
@implementation ShellWindowController
@@ -22,8 +24,10 @@
@end
-ShellWindowCocoa::ShellWindowCocoa(ExtensionHost* host)
- : ShellWindow(host),
+ShellWindowCocoa::ShellWindowCocoa(Profile* profile,
+ const Extension* extension,
+ const GURL& url)
+ : ShellWindow(profile, extension, url),
attention_request_id_(0) {
NSRect rect = NSMakeRect(0, 0, kDefaultWidth, kDefaultHeight);
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask |
@@ -33,9 +37,9 @@ ShellWindowCocoa::ShellWindowCocoa(ExtensionHost* host)
styleMask:styleMask
backing:NSBackingStoreBuffered
defer:NO]);
- [window setTitle:base::SysUTF8ToNSString(host->extension()->name())];
+ [window setTitle:base::SysUTF8ToNSString(extension->name())];
- NSView* view = host->view()->native_view();
+ NSView* view = web_contents()->GetView()->GetNativeView();
[view setFrame:rect];
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[[window contentView] addSubview:view];
@@ -165,6 +169,8 @@ NSWindow* ShellWindowCocoa::window() const {
}
// static
-ShellWindow* ShellWindow::CreateShellWindow(ExtensionHost* host) {
- return new ShellWindowCocoa(host);
+ShellWindow* ShellWindow::CreateImpl(Profile* profile,
+ const Extension* extension,
+ const GURL& url) {
+ return new ShellWindowCocoa(profile, extension, url);
}
diff --git a/chrome/browser/ui/extensions/shell_window.cc b/chrome/browser/ui/extensions/shell_window.cc
index f624f95..0371ab7 100644
--- a/chrome/browser/ui/extensions/shell_window.cc
+++ b/chrome/browser/ui/extensions/shell_window.cc
@@ -8,14 +8,24 @@
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_tabs_module_constants.h"
#include "chrome/browser/extensions/extension_window_controller.h"
+#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_id.h"
#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_view_type.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_messages.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/renderer_preferences.h"
+
+using content::SiteInstance;
+using content::WebContents;
namespace internal {
@@ -26,7 +36,6 @@ class ShellWindowController : public ExtensionWindowController {
// Overriden from ExtensionWindowController
virtual int GetWindowId() const OVERRIDE;
virtual std::string GetWindowTypeText() const OVERRIDE;
- virtual base::DictionaryValue* CreateWindowValue() const OVERRIDE;
virtual base::DictionaryValue* CreateWindowValueWithTabs() const OVERRIDE;
virtual bool CanClose(Reason* reason) const OVERRIDE;
virtual void SetFullscreenMode(bool is_fullscreen,
@@ -49,15 +58,8 @@ int ShellWindowController::GetWindowId() const {
return static_cast<int>(shell_window_->session_id().id());
}
-namespace keys = extension_tabs_module_constants;
-
std::string ShellWindowController::GetWindowTypeText() const {
- return keys::kWindowTypeValueShell;
-}
-
-base::DictionaryValue* ShellWindowController::CreateWindowValue() const {
- DictionaryValue* result = ExtensionWindowController::CreateWindowValue();
- return result;
+ return extension_tabs_module_constants::kWindowTypeValueShell;
}
base::DictionaryValue* ShellWindowController::CreateWindowValueWithTabs()
@@ -79,48 +81,32 @@ void ShellWindowController::SetFullscreenMode(bool is_fullscreen,
ShellWindow* ShellWindow::Create(Profile* profile,
const Extension* extension,
const GURL& url) {
- ExtensionProcessManager* manager = profile->GetExtensionProcessManager();
- DCHECK(manager);
-
// This object will delete itself when the window is closed.
- return ShellWindow::CreateShellWindow(
- manager->CreateShellHost(extension, url));
-}
-
-void ShellWindow::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE:
- if (content::Details<ExtensionHost>(host_.get()) == details)
- Close();
- break;
- case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
- const Extension* unloaded_extension =
- content::Details<UnloadedExtensionInfo>(details)->extension;
- // We compare extension IDs and not Extension pointers since ExtensionHost
- // nulls out its Extension pointer when it gets this notification.
- if (host_->extension_id() == unloaded_extension->id())
- Close();
- break;
- }
- case content::NOTIFICATION_APP_TERMINATING:
- Close();
- break;
- default:
- NOTREACHED() << "Received unexpected notification";
- }
+ return ShellWindow::CreateImpl(profile, extension, url);
}
-ShellWindow::ShellWindow(ExtensionHost* host)
- : host_(host) {
- // Close the window in response to window.close() and the like.
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
- content::Source<Profile>(host->profile()));
- // Also close if the window if the extension has been unloaded (parallels
- // NOTIFICATION_EXTENSION_UNLOADED closing the app's tabs in TabStripModel).
+ShellWindow::ShellWindow(Profile* profile,
+ const Extension* extension,
+ const GURL& url)
+ : profile_(profile),
+ extension_(extension),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ extension_function_dispatcher_(profile, this)) {
+ web_contents_.reset(WebContents::Create(
+ profile, SiteInstance::CreateForURL(profile, url), MSG_ROUTING_NONE, NULL,
+ NULL));
+ content::WebContentsObserver::Observe(web_contents_.get());
+ web_contents_->SetDelegate(this);
+ web_contents_->SetViewType(chrome::VIEW_TYPE_APP_SHELL);
+ web_contents_->GetMutableRendererPrefs()->browser_handles_all_requests =
+ true;
+ web_contents_->GetRenderViewHost()->SyncRendererPrefs();
+
+ web_contents_->GetController().LoadURL(
+ url, content::Referrer(), content::PAGE_TRANSITION_LINK,
+ std::string());
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
- content::Source<Profile>(host->profile()));
+ content::Source<Profile>(profile_));
// Close when the browser is exiting.
// TODO(mihaip): we probably don't want this in the long run (when platform
// apps are no longer tied to the browser process).
@@ -132,7 +118,9 @@ ShellWindow::ShellWindow(ExtensionHost* host)
// Make this window available to the extension API.
extension_window_controller_.reset(
- new internal::ShellWindowController(this, host->profile()));
+ new internal::ShellWindowController(this, profile_));
+
+ ShellWindowRegistry::Get(profile_)->AddShellWindow(this);
}
ShellWindow::~ShellWindow() {
@@ -140,6 +128,56 @@ ShellWindow::~ShellWindow() {
// last window open.
registrar_.RemoveAll();
+ ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
+
// Remove shutdown prevention.
BrowserList::EndKeepAlive();
}
+
+bool ShellWindow::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ShellWindow, message)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ShellWindow::CloseContents(WebContents* contents) {
+ Close();
+}
+
+// TODO(benwells): Rearrange so users of this can call
+// WebContents::set_should_suppress_dialogs(bool) instead of overriding
+// this delegate function.
+bool ShellWindow::ShouldSuppressDialogs() {
+ return true;
+}
+
+void ShellWindow::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
+ const Extension* unloaded_extension =
+ content::Details<UnloadedExtensionInfo>(details)->extension;
+ if (extension_ == unloaded_extension)
+ Close();
+ break;
+ }
+ case content::NOTIFICATION_APP_TERMINATING:
+ Close();
+ break;
+ default:
+ NOTREACHED() << "Received unexpected notification";
+ }
+}
+
+ExtensionWindowController* ShellWindow::GetExtensionWindowController() const {
+ return extension_window_controller_.get();
+}
+
+void ShellWindow::OnRequest(const ExtensionHostMsg_Request_Params& params) {
+ extension_function_dispatcher_.Dispatch(params,
+ web_contents_->GetRenderViewHost());
+}
diff --git a/chrome/browser/ui/extensions/shell_window.h b/chrome/browser/ui/extensions/shell_window.h
index 2790b74..dec4dd8 100644
--- a/chrome/browser/ui/extensions/shell_window.h
+++ b/chrome/browser/ui/extensions/shell_window.h
@@ -7,14 +7,15 @@
#pragma once
#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/sessions/session_id.h"
-#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/ui/base_window.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
class Extension;
-class ExtensionHost;
class ExtensionWindowController;
class GURL;
class Profile;
@@ -23,43 +24,74 @@ namespace content {
class WebContents;
}
+// ShellWindow is the type of window used by platform apps. Shell windows
+// have a WebContents but none of the chrome of normal browser windows.
class ShellWindow : public content::NotificationObserver,
+ public content::WebContentsDelegate,
+ public content::WebContentsObserver,
+ public ExtensionFunctionDispatcher::Delegate,
public BaseWindow {
public:
- // TODO(mihaip): Switch from hardcoded defaults to passing in the window
- // creation parameters to ShellWindow::Create.
- static const int kDefaultWidth = 512;
- static const int kDefaultHeight = 384;
+ static ShellWindow* Create(Profile* profile,
+ const Extension* extension,
+ const GURL& url);
- content::WebContents* web_contents() const { return host_->host_contents(); }
const SessionID& session_id() const { return session_id_; }
const ExtensionWindowController* extension_window_controller() const {
return extension_window_controller_.get();
}
- static ShellWindow* Create(Profile* profile,
- const Extension* extension,
- const GURL& url);
+ protected:
+ // TODO(mihaip): Switch from hardcoded defaults to passing in the window
+ // creation parameters to ShellWindow::Create.
+ static const int kDefaultWidth = 512;
+ static const int kDefaultHeight = 384;
+
+ ShellWindow(Profile* profile,
+ const Extension* extension,
+ const GURL& url);
+ virtual ~ShellWindow();
+
+ const Extension* extension() const { return extension_; }
+ content::WebContents* web_contents() const { return web_contents_.get(); }
+
+ private:
+ // PlatformAppBrowserTest needs access to web_contents()
+ friend class PlatformAppBrowserTest;
+
+ // Instantiates a platform-specific ShellWindow subclass (one implementation
+ // per platform). Public users of ShellWindow should use ShellWindow::Create.
+ static ShellWindow* CreateImpl(Profile* profile,
+ const Extension* extension,
+ const GURL& url);
+
+ // content::WebContentsObserver
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // content::WebContentsDelegate
+ virtual void CloseContents(content::WebContents* contents) OVERRIDE;
+ virtual bool ShouldSuppressDialogs() OVERRIDE;
// content::NotificationObserver implementation.
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- protected:
- explicit ShellWindow(ExtensionHost* host_);
- virtual ~ShellWindow();
+ virtual ExtensionWindowController* GetExtensionWindowController() const
+ OVERRIDE;
- // Instantiates a platform-specific ShellWindow subclass (one implementation
- // per platform). Public users of ShellWindow should use ShellWindow::Create.
- static ShellWindow* CreateShellWindow(ExtensionHost* host);
+ // Message handlers.
+ void OnRequest(const ExtensionHostMsg_Request_Params& params);
+
+ Profile* profile_; // weak pointer - owned by ProfileManager.
+ const Extension* extension_; // weak pointer - owned by ExtensionService.
const SessionID session_id_;
- scoped_ptr<ExtensionHost> host_;
+ scoped_ptr<content::WebContents> web_contents_;
content::NotificationRegistrar registrar_;
scoped_ptr<ExtensionWindowController> extension_window_controller_;
+ ExtensionFunctionDispatcher extension_function_dispatcher_;
- private:
DISALLOW_COPY_AND_ASSIGN(ShellWindow);
};
diff --git a/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc b/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc
index 0dce063..04aaf78 100644
--- a/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc
+++ b/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc
@@ -4,25 +4,28 @@
#include "chrome/browser/ui/gtk/extensions/shell_window_gtk.h"
-#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
#include "ui/base/x/active_window_watcher_x.h"
#include "ui/gfx/rect.h"
-ShellWindowGtk::ShellWindowGtk(ExtensionHost* host)
- : ShellWindow(host),
+ShellWindowGtk::ShellWindowGtk(Profile* profile,
+ const Extension* extension,
+ const GURL& url)
+ : ShellWindow(profile, extension, url),
state_(GDK_WINDOW_STATE_WITHDRAWN),
is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()) {
- host_->view()->SetContainer(this);
window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
- gtk_container_add(GTK_CONTAINER(window_), host_->view()->native_view());
+ gfx::NativeView native_view =
+ web_contents()->GetView()->GetNativeView();
+ gtk_container_add(GTK_CONTAINER(window_), native_view);
gtk_window_set_default_size(window_, kDefaultWidth, kDefaultHeight);
- const Extension* extension = host_->extension();
-
// TODO(mihaip): Mirror contents of <title> tag in window title
gtk_window_set_title(window_, extension->name().c_str());
@@ -164,6 +167,8 @@ gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender,
}
// static
-ShellWindow* ShellWindow::CreateShellWindow(ExtensionHost* host) {
- return new ShellWindowGtk(host);
+ShellWindow* ShellWindow::CreateImpl(Profile* profile,
+ const Extension* extension,
+ const GURL& url) {
+ return new ShellWindowGtk(profile, extension, url);
}
diff --git a/chrome/browser/ui/gtk/extensions/shell_window_gtk.h b/chrome/browser/ui/gtk/extensions/shell_window_gtk.h
index 3745548..1e14c89 100644
--- a/chrome/browser/ui/gtk/extensions/shell_window_gtk.h
+++ b/chrome/browser/ui/gtk/extensions/shell_window_gtk.h
@@ -14,13 +14,15 @@
#include "ui/base/x/active_window_watcher_x_observer.h"
#include "ui/gfx/rect.h"
-class ExtensionHost;
+class Profile;
class ShellWindowGtk : public ShellWindow,
public ExtensionViewGtk::Container,
public ui::ActiveWindowWatcherXObserver {
public:
- explicit ShellWindowGtk(ExtensionHost* host);
+ ShellWindowGtk(Profile* profile,
+ const Extension* extension,
+ const GURL& url);
// BaseWindow implementation.
virtual bool IsActive() const OVERRIDE;
diff --git a/chrome/browser/ui/views/extensions/shell_window_views.cc b/chrome/browser/ui/views/extensions/shell_window_views.cc
index ef37058..fd39285 100644
--- a/chrome/browser/ui/views/extensions/shell_window_views.cc
+++ b/chrome/browser/ui/views/extensions/shell_window_views.cc
@@ -7,6 +7,10 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/common/extensions/extension.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/path.h"
#include "ui/gfx/scoped_sk_region.h"
@@ -17,8 +21,6 @@
#if defined(OS_WIN) && !defined(USE_AURA)
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/web_applications/web_app.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host_view.h"
#include "ui/base/win/shell.h"
#endif
@@ -96,9 +98,11 @@ void ShellWindowFrameView::GetWindowMask(const gfx::Size& size,
// Don't touch it.
}
-ShellWindowViews::ShellWindowViews(ExtensionHost* host)
- : ShellWindow(host) {
- host_->view()->SetContainer(this);
+ShellWindowViews::ShellWindowViews(Profile* profile,
+ const Extension* extension,
+ const GURL& url)
+ : ShellWindow(profile, extension, url),
+ initialized_(false) {
window_ = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
params.delegate = this;
@@ -108,13 +112,12 @@ ShellWindowViews::ShellWindowViews(ExtensionHost* host)
window_->Init(params);
#if defined(OS_WIN) && !defined(USE_AURA)
std::string app_name = web_app::GenerateApplicationNameFromExtensionId(
- host_->extension()->id());
+ extension->id());
ui::win::SetAppIdForWindow(
ShellIntegration::GetAppId(UTF8ToWide(app_name),
- host_->profile()->GetPath()),
+ profile->GetPath()),
GetWidget()->GetTopLevelWidget()->GetNativeWindow());
#endif
- AddChildView(host_->view());
SetLayoutManager(new views::FillLayout);
Layout();
@@ -122,6 +125,8 @@ ShellWindowViews::ShellWindowViews(ExtensionHost* host)
}
ShellWindowViews::~ShellWindowViews() {
+ if (initialized_)
+ NativeViewHost::Detach();
}
bool ShellWindowViews::IsActive() const {
@@ -234,7 +239,7 @@ views::NonClientFrameView* ShellWindowViews::CreateNonClientFrameView(
}
string16 ShellWindowViews::GetWindowTitle() const {
- return UTF8ToUTF16(host_->extension()->name());
+ return UTF8ToUTF16(extension()->name());
}
views::Widget* ShellWindowViews::GetWidget() {
@@ -249,7 +254,7 @@ void ShellWindowViews::OnViewWasResized() {
// TODO(jeremya): this doesn't seem like a terribly elegant way to keep the
// window shape in sync.
#if defined(OS_WIN) && !defined(USE_AURA)
- gfx::Size sz = host_->view()->size();
+ gfx::Size sz = size();
int height = sz.height(), width = sz.width();
int radius = 1;
gfx::Path path;
@@ -267,7 +272,7 @@ void ShellWindowViews::OnViewWasResized() {
path.lineTo(0, height - radius - 1);
path.close();
}
- SetWindowRgn(host_->view()->native_view(), path.CreateNativeRegion(), 1);
+ SetWindowRgn(native_view(), path.CreateNativeRegion(), 1);
SkRegion* rgn = new SkRegion;
if (caption_region_.Get())
@@ -278,11 +283,67 @@ void ShellWindowViews::OnViewWasResized() {
rgn->op(width - kResizeBorderWidth, 0, width, height, SkRegion::kUnion_Op);
rgn->op(0, height - kResizeBorderWidth, width, height, SkRegion::kUnion_Op);
}
- host_->render_view_host()->GetView()->SetClickthroughRegion(rgn);
+ web_contents()->GetRenderViewHost()->GetView()->SetClickthroughRegion(rgn);
#endif
}
+gfx::NativeCursor ShellWindowViews::GetCursor(const views::MouseEvent& event) {
+ return gfx::kNullCursor;
+}
+
+void ShellWindowViews::SetVisible(bool is_visible) {
+ if (is_visible != visible()) {
+ NativeViewHost::SetVisible(is_visible);
+
+ // Also tell RenderWidgetHostView the new visibility. Despite its name, it
+ // is not part of the View hierarchy and does not know about the change
+ // unless we tell it.
+ content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
+ if (rvh->GetView()) {
+ if (is_visible)
+ rvh->GetView()->Show();
+ else
+ rvh->GetView()->Hide();
+ }
+ }
+}
+
+void ShellWindowViews::ViewHierarchyChanged(bool is_add,
+ views::View *parent,
+ views::View *child) {
+ NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
+ if (is_add && GetWidget() && !initialized_) {
+ initialized_ = true;
+ NativeViewHost::Attach(web_contents()->GetView()->GetNativeView());
+ }
+}
+
+void ShellWindowViews::PreferredSizeChanged() {
+ View::PreferredSizeChanged();
+}
+
+bool ShellWindowViews::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
+ // Let the tab key event be processed by the renderer (instead of moving the
+ // focus to the next focusable view). Also handle Backspace, since otherwise
+ // (on Windows at least), pressing Backspace, when focus is on a text field
+ // within the ExtensionView, will navigate the page back instead of erasing a
+ // character.
+ return (e.key_code() == ui::VKEY_TAB || e.key_code() == ui::VKEY_BACK);
+}
+
+void ShellWindowViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+ // Propagate the new size to RenderWidgetHostView.
+ // We can't send size zero because RenderWidget DCHECKs that.
+ content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
+ if (rvh->GetView() && !bounds().IsEmpty()) {
+ rvh->GetView()->SetSize(size());
+ OnViewWasResized();
+ }
+}
+
// static
-ShellWindow* ShellWindow::CreateShellWindow(ExtensionHost* host) {
- return new ShellWindowViews(host);
+ShellWindow* ShellWindow::CreateImpl(Profile* profile,
+ const Extension* extension,
+ const GURL& url) {
+ return new ShellWindowViews(profile, extension, url);
}
diff --git a/chrome/browser/ui/views/extensions/shell_window_views.h b/chrome/browser/ui/views/extensions/shell_window_views.h
index ba4b776..063c9e8 100644
--- a/chrome/browser/ui/views/extensions/shell_window_views.h
+++ b/chrome/browser/ui/views/extensions/shell_window_views.h
@@ -7,18 +7,20 @@
#pragma once
#include "chrome/browser/ui/extensions/shell_window.h"
-#include "chrome/browser/ui/views/extensions/extension_view.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/scoped_sk_region.h"
+#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/widget/widget_delegate.h"
-class ExtensionHost;
+class Profile;
class ShellWindowViews : public ShellWindow,
- public ExtensionView::Container,
- public views::WidgetDelegateView {
+ public views::NativeViewHost,
+ public views::WidgetDelegate {
public:
- explicit ShellWindowViews(ExtensionHost* host);
+ ShellWindowViews(Profile* profile,
+ const Extension* extension,
+ const GURL& url);
// BaseWindow implementation.
virtual bool IsActive() const OVERRIDE;
@@ -51,12 +53,24 @@ class ShellWindowViews : public ShellWindow,
virtual string16 GetWindowTitle() const OVERRIDE;
virtual void DeleteDelegate() OVERRIDE;
- // ExtensionView::Container implementation.
- virtual void OnViewWasResized() OVERRIDE;
+ // Overridden from views::NativeViewHost:
+ virtual gfx::NativeCursor GetCursor(const views::MouseEvent& event) OVERRIDE;
+ virtual void SetVisible(bool is_visible) OVERRIDE;
+ virtual void ViewHierarchyChanged(
+ bool is_add, views::View *parent, views::View *child) OVERRIDE;
+
+ protected:
+ // Overridden from views::View.
+ virtual void PreferredSizeChanged() OVERRIDE;
+ virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e) OVERRIDE;
+ virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
private:
virtual ~ShellWindowViews();
+ void OnViewWasResized();
+
+ bool initialized_;
views::Widget* window_;
gfx::ScopedSkRegion caption_region_;
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index bece4a8..b715547 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -415,6 +415,8 @@
'browser/extensions/settings/testing_settings_storage.h',
'browser/extensions/settings/weak_unlimited_settings_storage.cc',
'browser/extensions/settings/weak_unlimited_settings_storage.h',
+ 'browser/extensions/shell_window_registry.cc',
+ 'browser/extensions/shell_window_registry.h',
'browser/extensions/theme_installed_infobar_delegate.cc',
'browser/extensions/theme_installed_infobar_delegate.h',
'browser/extensions/unpacked_installer.cc',
diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h
index 50b3200..d31bd5b 100644
--- a/chrome/common/chrome_notification_types.h
+++ b/chrome/common/chrome_notification_types.h
@@ -529,6 +529,14 @@ enum NotificationType {
// ExtensionAction* that changed. The details are a WebContents*.
NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
+ // A new extension RenderViewHost has been registered. The details are
+ // the RenderViewHost*.
+ NOTIFICATION_EXTENSION_VIEW_REGISTERED,
+
+ // An extension RenderViewHost has been unregistered. The details are
+ // the RenderViewHost*.
+ NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
+
// Sent by an extension to notify the browser about the results of a unit
// test.
NOTIFICATION_EXTENSION_TEST_PASSED,