summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,