From 6b67ec749d2a0d21f219125da55f7a3347710984 Mon Sep 17 00:00:00 2001 From: "jamescook@chromium.org" Date: Sat, 22 Feb 2014 19:53:59 +0000 Subject: Add support for chrome.app.window.create() to app_shell * Introduce an AppsClient for app_shell * Create an AppsClient for tests * Introduce ShellAppWindowDelegate whose sole purpose is to create a NativeAppWindowViews for windows in app_shell * Extract Chrome-specific code from apps/app_window.cc This is part 2 of 2 and depends on https://codereview.chromium.org/171003004/ BUG=343174 TEST=browser_tests PlatformApp* TBR=sky@chromium.org for chrome/test/base/testing_browser_process.cc Review URL: https://codereview.chromium.org/166833004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@252820 0039d316-1c4b-4281-b951-d872f2087c98 --- apps/app_window.cc | 6 +- apps/apps.gypi | 4 ++ apps/apps_client.h | 13 ++++ apps/shell/browser/shell_app_window_delegate.cc | 81 ++++++++++++++++++++++ apps/shell/browser/shell_app_window_delegate.h | 57 +++++++++++++++ apps/shell/browser/shell_apps_client.cc | 40 +++++++++++ apps/shell/browser/shell_apps_client.h | 44 ++++++++++++ apps/shell/browser/shell_browser_main_parts.cc | 5 ++ apps/shell/browser/shell_browser_main_parts.h | 2 + apps/shell/browser/shell_extension_system.cc | 7 ++ apps/shell/browser/shell_extension_system.h | 6 ++ chrome/browser/apps/chrome_apps_client.cc | 30 ++++++++ chrome/browser/apps/chrome_apps_client.h | 8 ++- .../extensions/api/app_window/app_window_api.cc | 6 +- chrome/test/base/testing_browser_process.cc | 2 + 15 files changed, 302 insertions(+), 9 deletions(-) create mode 100644 apps/shell/browser/shell_app_window_delegate.cc create mode 100644 apps/shell/browser/shell_app_window_delegate.h create mode 100644 apps/shell/browser/shell_apps_client.cc create mode 100644 apps/shell/browser/shell_apps_client.h diff --git a/apps/app_window.cc b/apps/app_window.cc index 1f0c945..1c6d286 100644 --- a/apps/app_window.cc +++ b/apps/app_window.cc @@ -6,6 +6,7 @@ #include "apps/app_window_geometry_cache.h" #include "apps/app_window_registry.h" +#include "apps/apps_client.h" #include "apps/ui/native_app_window.h" #include "base/command_line.h" #include "base/strings/string_util.h" @@ -14,7 +15,6 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_web_contents_observer.h" #include "chrome/browser/extensions/suggest_permission_util.h" -#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_messages.h" #include "chrome/common/extensions/manifest_handlers/icons_handler.h" @@ -232,7 +232,7 @@ void AppWindow::Init(const GURL& url, } // Prevent the browser process from shutting down while this window is open. - chrome::StartKeepAlive(); + AppsClient::Get()->StartKeepAlive(); UpdateExtensionAppIcon(); @@ -245,7 +245,7 @@ AppWindow::~AppWindow() { registrar_.RemoveAll(); // Remove shutdown prevention. - chrome::EndKeepAlive(); + AppsClient::Get()->EndKeepAlive(); } void AppWindow::RequestMediaAccessPermission( diff --git a/apps/apps.gypi b/apps/apps.gypi index eef1adf..c5ef863 100644 --- a/apps/apps.gypi +++ b/apps/apps.gypi @@ -161,6 +161,10 @@ 'shell/app/shell_main.cc', 'shell/browser/shell_app_sorting.cc', 'shell/browser/shell_app_sorting.h', + 'shell/browser/shell_app_window_delegate.cc', + 'shell/browser/shell_app_window_delegate.h', + 'shell/browser/shell_apps_client.cc', + 'shell/browser/shell_apps_client.h', 'shell/browser/shell_browser_context.cc', 'shell/browser/shell_browser_context.h', 'shell/browser/shell_browser_main_parts.cc', diff --git a/apps/apps_client.h b/apps/apps_client.h index f67aad6..bd5474c 100644 --- a/apps/apps_client.h +++ b/apps/apps_client.h @@ -17,6 +17,8 @@ class Extension; namespace apps { +class AppWindow; + // Sets up global state for the apps system. Should be Set() once in each // process. This should be implemented by the client of the apps system. class AppsClient { @@ -29,6 +31,17 @@ class AppsClient { virtual bool CheckAppLaunch(content::BrowserContext* context, const extensions::Extension* extension) = 0; + // Creates a new apps::AppWindow for the app in |extension| for |context|. + // Caller takes ownership. + virtual AppWindow* CreateAppWindow( + content::BrowserContext* context, + const extensions::Extension* extension) = 0; + + // Tells the embedding application to stay running. The application may close + // after a matching number of calls to EndKeepAlive() are made. + virtual void StartKeepAlive() = 0; + virtual void EndKeepAlive() = 0; + // Return the apps client. static AppsClient* Get(); diff --git a/apps/shell/browser/shell_app_window_delegate.cc b/apps/shell/browser/shell_app_window_delegate.cc new file mode 100644 index 0000000..11b0f83 --- /dev/null +++ b/apps/shell/browser/shell_app_window_delegate.cc @@ -0,0 +1,81 @@ +// Copyright 2014 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 "apps/shell/browser/shell_app_window_delegate.h" + +#include "apps/ui/views/base_native_app_window_views.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_view.h" +#include "ui/aura/window.h" + +namespace apps { + +ShellAppWindowDelegate::ShellAppWindowDelegate() {} + +ShellAppWindowDelegate::~ShellAppWindowDelegate() {} + +void ShellAppWindowDelegate::InitWebContents( + content::WebContents* web_contents) {} + +NativeAppWindow* ShellAppWindowDelegate::CreateNativeAppWindow( + AppWindow* window, + const AppWindow::CreateParams& params) { + BaseNativeAppWindowViews* native_app_window = new BaseNativeAppWindowViews; + native_app_window->Init(window, params); + return native_app_window; +} + +content::WebContents* ShellAppWindowDelegate::OpenURLFromTab( + content::BrowserContext* context, + content::WebContents* source, + const content::OpenURLParams& params) { + return NULL; +} + +void ShellAppWindowDelegate::AddNewContents(content::BrowserContext* context, + content::WebContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture, + bool* was_blocked) { + LOG(ERROR) << "app_shell does not support opening a new tab/window."; +} + +content::ColorChooser* ShellAppWindowDelegate::ShowColorChooser( + content::WebContents* web_contents, + SkColor initial_color) { + return NULL; +} + +void ShellAppWindowDelegate::RunFileChooser( + content::WebContents* tab, + const content::FileChooserParams& params) { + LOG(ERROR) << "app_shell does not support file pickers."; +} + +void ShellAppWindowDelegate::RequestMediaAccessPermission( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback, + const extensions::Extension* extension) { + // TODO(jamescook): Support media capture. + LOG(ERROR) << "app_shell does not support media capture."; +} + +int ShellAppWindowDelegate::PreferredIconSize() { + // Pick an arbitrary size. + return 32; +} + +void ShellAppWindowDelegate::SetWebContentsBlocked( + content::WebContents* web_contents, + bool blocked) {} + +bool ShellAppWindowDelegate::IsWebContentsVisible( + content::WebContents* web_contents) { + aura::Window* native_window = web_contents->GetView()->GetNativeView(); + return native_window->IsVisible(); +} + +} // namespace apps diff --git a/apps/shell/browser/shell_app_window_delegate.h b/apps/shell/browser/shell_app_window_delegate.h new file mode 100644 index 0000000..56b38f2 --- /dev/null +++ b/apps/shell/browser/shell_app_window_delegate.h @@ -0,0 +1,57 @@ +// Copyright 2014 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 APPS_SHELL_BROWSER_SHELL_APP_WINDOW_DELEGATE_H_ +#define APPS_SHELL_BROWSER_SHELL_APP_WINDOW_DELEGATE_H_ + +#include "apps/app_window.h" + +namespace apps { + +// The AppWindow::Delegate for app_shell. Used to create instances of +// NativeAppWindow. Other functionality is not supported. +class ShellAppWindowDelegate : public AppWindow::Delegate { + public: + ShellAppWindowDelegate(); + virtual ~ShellAppWindowDelegate(); + + private: + // ShellWindow::Delegate: + virtual void InitWebContents(content::WebContents* web_contents) OVERRIDE; + virtual NativeAppWindow* CreateNativeAppWindow( + AppWindow* window, + const AppWindow::CreateParams& params) OVERRIDE; + virtual content::WebContents* OpenURLFromTab( + content::BrowserContext* context, + content::WebContents* source, + const content::OpenURLParams& params) OVERRIDE; + virtual void AddNewContents(content::BrowserContext* context, + content::WebContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture, + bool* was_blocked) OVERRIDE; + virtual content::ColorChooser* ShowColorChooser( + content::WebContents* web_contents, + SkColor initial_color) OVERRIDE; + virtual void RunFileChooser(content::WebContents* tab, + const content::FileChooserParams& params) + OVERRIDE; + virtual void RequestMediaAccessPermission( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback, + const extensions::Extension* extension) OVERRIDE; + virtual int PreferredIconSize() OVERRIDE; + virtual void SetWebContentsBlocked(content::WebContents* web_contents, + bool blocked) OVERRIDE; + virtual bool IsWebContentsVisible(content::WebContents* web_contents) + OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(ShellAppWindowDelegate); +}; + +} // namespace apps + +#endif // APPS_SHELL_BROWSER_SHELL_APP_WINDOW_DELEGATE_H_ diff --git a/apps/shell/browser/shell_apps_client.cc b/apps/shell/browser/shell_apps_client.cc new file mode 100644 index 0000000..c7d877e1 --- /dev/null +++ b/apps/shell/browser/shell_apps_client.cc @@ -0,0 +1,40 @@ +// Copyright 2014 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 "apps/shell/browser/shell_apps_client.h" + +#include "apps/app_window.h" +#include "apps/shell/browser/shell_app_window_delegate.h" + +using content::BrowserContext; + +namespace apps { + +ShellAppsClient::ShellAppsClient(BrowserContext* browser_context) + : browser_context_(browser_context) {} + +ShellAppsClient::~ShellAppsClient() {} + +std::vector ShellAppsClient::GetLoadedBrowserContexts() { + std::vector browser_contexts; + browser_contexts.push_back(browser_context_); + return browser_contexts; +} + +bool ShellAppsClient::CheckAppLaunch(BrowserContext* context, + const extensions::Extension* extension) { + return true; +} + +AppWindow* ShellAppsClient::CreateAppWindow( + BrowserContext* context, + const extensions::Extension* extension) { + return new AppWindow(context, new ShellAppWindowDelegate, extension); +} + +void ShellAppsClient::StartKeepAlive() {} + +void ShellAppsClient::EndKeepAlive() {} + +} // namespace apps diff --git a/apps/shell/browser/shell_apps_client.h b/apps/shell/browser/shell_apps_client.h new file mode 100644 index 0000000..df96dbe --- /dev/null +++ b/apps/shell/browser/shell_apps_client.h @@ -0,0 +1,44 @@ +// Copyright 2014 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 APPS_SHELL_BROWSER_SHELL_APPS_CLIENT_H_ +#define APPS_SHELL_BROWSER_SHELL_APPS_CLIENT_H_ + +#include "apps/apps_client.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" + +namespace content { +class BrowserContext; +} + +namespace apps { + +// The implementation of AppsClient for app_shell. +class ShellAppsClient : public AppsClient { + public: + // For app_shell only a single browser context is supported. + explicit ShellAppsClient(content::BrowserContext* browser_context); + virtual ~ShellAppsClient(); + + private: + // apps::AppsClient implementation: + virtual std::vector GetLoadedBrowserContexts() + OVERRIDE; + virtual bool CheckAppLaunch(content::BrowserContext* context, + const extensions::Extension* extension) OVERRIDE; + virtual AppWindow* CreateAppWindow(content::BrowserContext* context, + const extensions::Extension* extension) + OVERRIDE; + virtual void StartKeepAlive() OVERRIDE; + virtual void EndKeepAlive() OVERRIDE; + + content::BrowserContext* browser_context_; + + DISALLOW_COPY_AND_ASSIGN(ShellAppsClient); +}; + +} // namespace apps + +#endif // APPS_SHELL_BROWSER_SHELL_APPS_CLIENT_H_ diff --git a/apps/shell/browser/shell_browser_main_parts.cc b/apps/shell/browser/shell_browser_main_parts.cc index 9159481..dae80bb 100644 --- a/apps/shell/browser/shell_browser_main_parts.cc +++ b/apps/shell/browser/shell_browser_main_parts.cc @@ -4,6 +4,7 @@ #include "apps/shell/browser/shell_browser_main_parts.h" +#include "apps/shell/browser/shell_apps_client.h" #include "apps/shell/browser/shell_browser_context.h" #include "apps/shell/browser/shell_extension_system.h" #include "apps/shell/browser/shell_extension_system_factory.h" @@ -111,6 +112,9 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() { new extensions::ShellExtensionsBrowserClient(browser_context_.get())); extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get()); + apps_client_.reset(new ShellAppsClient(browser_context_.get())); + AppsClient::Set(apps_client_.get()); + // Create our custom ExtensionSystem first because other // BrowserContextKeyedServices depend on it. // TODO(yoz): Move this after EnsureBrowserContextKeyedServiceFactoriesBuilt. @@ -163,6 +167,7 @@ void ShellBrowserMainParts::PostMainMessageLoopRun() { void ShellBrowserMainParts::OnWindowTreeHostCloseRequested( const aura::WindowEventDispatcher* dispatcher) { + extension_system_->CloseApp(); base::MessageLoop::current()->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); } diff --git a/apps/shell/browser/shell_browser_main_parts.h b/apps/shell/browser/shell_browser_main_parts.h index f9fae2e..d8746d8 100644 --- a/apps/shell/browser/shell_browser_main_parts.h +++ b/apps/shell/browser/shell_browser_main_parts.h @@ -40,6 +40,7 @@ class WMTestHelper; namespace apps { +class ShellAppsClient; class ShellBrowserContext; class ShellExtensionsClient; @@ -90,6 +91,7 @@ class ShellBrowserMainParts : public content::BrowserMainParts, scoped_ptr extensions_client_; scoped_ptr extensions_browser_client_; + scoped_ptr apps_client_; scoped_ptr net_log_; // Enable a minimal set of views::corewm to be initialized. diff --git a/apps/shell/browser/shell_extension_system.cc b/apps/shell/browser/shell_extension_system.cc index 549931a..6defb0e 100644 --- a/apps/shell/browser/shell_extension_system.cc +++ b/apps/shell/browser/shell_extension_system.cc @@ -6,6 +6,7 @@ #include +#include "apps/app_window_registry.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "chrome/browser/chrome_notification_types.h" @@ -48,6 +49,7 @@ bool ShellExtensionSystem::LoadAndLaunchApp(const base::FilePath& app_dir) { << " failed with: " << load_error; return false; } + app_id_ = extension->id(); // TODO(jamescook): We may want to do some of these things here: // * Create a PermissionsUpdater. @@ -86,6 +88,11 @@ bool ShellExtensionSystem::LoadAndLaunchApp(const base::FilePath& app_dir) { return true; } +void ShellExtensionSystem::CloseApp() { + apps::AppWindowRegistry::Get(browser_context_) + ->CloseAllAppWindowsForApp(app_id_); +} + void ShellExtensionSystem::Shutdown() { } diff --git a/apps/shell/browser/shell_extension_system.h b/apps/shell/browser/shell_extension_system.h index 85e3392..39004117 100644 --- a/apps/shell/browser/shell_extension_system.h +++ b/apps/shell/browser/shell_extension_system.h @@ -40,6 +40,9 @@ class ShellExtensionSystem : public ExtensionSystem { // Returns true on success. bool LoadAndLaunchApp(const base::FilePath& app_dir); + // Closes the running app. + void CloseApp(); + // BrowserContextKeyedService implementation: virtual void Shutdown() OVERRIDE; @@ -71,6 +74,9 @@ class ShellExtensionSystem : public ExtensionSystem { private: content::BrowserContext* browser_context_; // Not owned. + // Extension ID for the app. + std::string app_id_; + // Data to be accessed on the IO thread. Must outlive process_manager_. scoped_refptr info_map_; diff --git a/chrome/browser/apps/chrome_apps_client.cc b/chrome/browser/apps/chrome_apps_client.cc index 25d2153..0ce9022 100644 --- a/chrome/browser/apps/chrome_apps_client.cc +++ b/chrome/browser/apps/chrome_apps_client.cc @@ -4,6 +4,7 @@ #include "chrome/browser/apps/chrome_apps_client.h" +#include "apps/app_window.h" #include "base/memory/singleton.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_manager.h" @@ -14,6 +15,13 @@ #include "win8/util/win8_util.h" #endif +// TODO(jamescook): We probably shouldn't compile this class at all on Android. +// See http://crbug.com/343612 +#if !defined(OS_ANDROID) +#include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/ui/apps/chrome_app_window_delegate.h" +#endif + ChromeAppsClient::ChromeAppsClient() {} ChromeAppsClient::~ChromeAppsClient() {} @@ -47,3 +55,25 @@ bool ChromeAppsClient::CheckAppLaunch(content::BrowserContext* context, #endif return true; } + +apps::AppWindow* ChromeAppsClient::CreateAppWindow( + content::BrowserContext* context, + const extensions::Extension* extension) { +#if defined(OS_ANDROID) + return NULL; +#else + return new apps::AppWindow(context, new ChromeAppWindowDelegate, extension); +#endif +} + +void ChromeAppsClient::StartKeepAlive() { +#if !defined(OS_ANDROID) + chrome::StartKeepAlive(); +#endif +} + +void ChromeAppsClient::EndKeepAlive() { +#if !defined(OS_ANDROID) + chrome::EndKeepAlive(); +#endif +} diff --git a/chrome/browser/apps/chrome_apps_client.h b/chrome/browser/apps/chrome_apps_client.h index 06273d1..e3e7211 100644 --- a/chrome/browser/apps/chrome_apps_client.h +++ b/chrome/browser/apps/chrome_apps_client.h @@ -26,11 +26,13 @@ class ChromeAppsClient : public apps::AppsClient { // apps::AppsClient virtual std::vector GetLoadedBrowserContexts() OVERRIDE; - - // Do any pre app launch checks. Returns true if the app launch should proceed - // or false if the launch should be prevented. virtual bool CheckAppLaunch(content::BrowserContext* context, const extensions::Extension* extension) OVERRIDE; + virtual apps::AppWindow* CreateAppWindow( + content::BrowserContext* context, + const extensions::Extension* extension) OVERRIDE; + virtual void StartKeepAlive() OVERRIDE; + virtual void EndKeepAlive() OVERRIDE; DISALLOW_COPY_AND_ASSIGN(ChromeAppsClient); }; diff --git a/chrome/browser/extensions/api/app_window/app_window_api.cc b/chrome/browser/extensions/api/app_window/app_window_api.cc index 658e085..66eeb94 100644 --- a/chrome/browser/extensions/api/app_window/app_window_api.cc +++ b/chrome/browser/extensions/api/app_window/app_window_api.cc @@ -7,6 +7,7 @@ #include "apps/app_window.h" #include "apps/app_window_contents.h" #include "apps/app_window_registry.h" +#include "apps/apps_client.h" #include "apps/ui/native_app_window.h" #include "base/command_line.h" #include "base/strings/string_number_conversions.h" @@ -17,7 +18,6 @@ #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" #include "chrome/browser/extensions/window_controller.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/apps/chrome_app_window_delegate.h" #include "chrome/common/extensions/api/app_window.h" #include "chrome/common/extensions/features/feature_channel.h" #include "content/public/browser/notification_registrar.h" @@ -269,8 +269,8 @@ bool AppWindowCreateFunction::RunImpl() { create_params.creator_process_id = render_view_host_->GetProcess()->GetID(); - AppWindow* app_window = new AppWindow( - GetProfile(), new ChromeAppWindowDelegate(), GetExtension()); + AppWindow* app_window = + apps::AppsClient::Get()->CreateAppWindow(GetProfile(), GetExtension()); app_window->Init( url, new apps::AppWindowContentsImpl(app_window), create_params); diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc index 5f74dfa..dc570aa 100644 --- a/chrome/test/base/testing_browser_process.cc +++ b/chrome/test/base/testing_browser_process.cc @@ -7,6 +7,7 @@ #include "base/prefs/pref_service.h" #include "base/strings/string_util.h" #include "build/build_config.h" +#include "chrome/browser/apps/chrome_apps_client.h" #include "chrome/browser/background/background_mode_manager.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_impl.h" @@ -73,6 +74,7 @@ TestingBrowserProcess::TestingBrowserProcess() extensions_browser_client_( new extensions::ChromeExtensionsBrowserClient) { extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get()); + apps::AppsClient::Set(ChromeAppsClient::GetInstance()); } TestingBrowserProcess::~TestingBrowserProcess() { -- cgit v1.1