summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authoryoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-24 03:39:36 +0000
committeryoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-24 03:39:36 +0000
commit7685f64a35b6d029f7d11ce752dc126163d9474e (patch)
tree0cb10d4ed10d781bc6de27672bbcc8528134baab /extensions
parentaf97fe7d55c6310aacf1585bdbd8d38e3bc4c080 (diff)
downloadchromium_src-7685f64a35b6d029f7d11ce752dc126163d9474e.zip
chromium_src-7685f64a35b6d029f7d11ce752dc126163d9474e.tar.gz
chromium_src-7685f64a35b6d029f7d11ce752dc126163d9474e.tar.bz2
Move apps/shell to extensions/shell.
This does: - Move files - Fix up all namespaces in these files to be extensions, not apps - Clean up DEPS files This does not: - Change the name of the build targets (app_shell, app_shell_browsertests) BUG=394987 TBR=ben@chromium.org Review URL: https://codereview.chromium.org/412713002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285144 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions')
-rw-r--r--extensions/DEPS1
-rw-r--r--extensions/renderer/DEPS2
-rw-r--r--extensions/shell/DEPS23
-rw-r--r--extensions/shell/OWNERS3
-rw-r--r--extensions/shell/README13
-rw-r--r--extensions/shell/app/DEPS7
-rw-r--r--extensions/shell/app/README5
-rw-r--r--extensions/shell/app/shell_main.cc32
-rw-r--r--extensions/shell/app/shell_main_delegate.cc109
-rw-r--r--extensions/shell/app/shell_main_delegate.h60
-rw-r--r--extensions/shell/app_shell.gyp223
-rw-r--r--extensions/shell/app_shell_resources.grd18
-rw-r--r--extensions/shell/browser/DEPS25
-rw-r--r--extensions/shell/browser/api/shell/shell_api.cc59
-rw-r--r--extensions/shell/browser/api/shell/shell_api.h33
-rw-r--r--extensions/shell/browser/default_shell_app_window_controller.cc45
-rw-r--r--extensions/shell/browser/default_shell_app_window_controller.h40
-rw-r--r--extensions/shell/browser/default_shell_browser_main_delegate.cc52
-rw-r--r--extensions/shell/browser/default_shell_browser_main_delegate.h32
-rw-r--r--extensions/shell/browser/dns_apitest.cc128
-rw-r--r--extensions/shell/browser/shell_app_sorting.cc105
-rw-r--r--extensions/shell/browser/shell_app_sorting.h63
-rw-r--r--extensions/shell/browser/shell_app_window.cc75
-rw-r--r--extensions/shell/browser/shell_app_window.h72
-rw-r--r--extensions/shell/browser/shell_app_window_controller.h30
-rw-r--r--extensions/shell/browser/shell_browser_context.cc70
-rw-r--r--extensions/shell/browser/shell_browser_context.h53
-rw-r--r--extensions/shell/browser/shell_browser_main_delegate.h36
-rw-r--r--extensions/shell/browser/shell_browser_main_parts.cc167
-rw-r--r--extensions/shell/browser/shell_browser_main_parts.h95
-rw-r--r--extensions/shell/browser/shell_browsertest.cc31
-rw-r--r--extensions/shell/browser/shell_content_browser_client.cc192
-rw-r--r--extensions/shell/browser/shell_content_browser_client.h73
-rw-r--r--extensions/shell/browser/shell_desktop_controller.cc336
-rw-r--r--extensions/shell/browser/shell_desktop_controller.h149
-rw-r--r--extensions/shell/browser/shell_extension_system.cc196
-rw-r--r--extensions/shell/browser/shell_extension_system.h102
-rw-r--r--extensions/shell/browser/shell_extension_system_factory.cc52
-rw-r--r--extensions/shell/browser/shell_extension_system_factory.h40
-rw-r--r--extensions/shell/browser/shell_extension_web_contents_observer.cc20
-rw-r--r--extensions/shell/browser/shell_extension_web_contents_observer.h29
-rw-r--r--extensions/shell/browser/shell_extensions_browser_client.cc242
-rw-r--r--extensions/shell/browser/shell_extensions_browser_client.h93
-rw-r--r--extensions/shell/browser/shell_network_controller_chromeos.cc210
-rw-r--r--extensions/shell/browser/shell_network_controller_chromeos.h86
-rw-r--r--extensions/shell/browser/shell_omaha_query_params_delegate.cc22
-rw-r--r--extensions/shell/browser/shell_omaha_query_params_delegate.h26
-rw-r--r--extensions/shell/browser/shell_runtime_api_delegate.cc66
-rw-r--r--extensions/shell/browser/shell_runtime_api_delegate.h36
-rw-r--r--extensions/shell/browser/shell_special_storage_policy.cc43
-rw-r--r--extensions/shell/browser/shell_special_storage_policy.h33
-rw-r--r--extensions/shell/common/api/_api_features.json18
-rw-r--r--extensions/shell/common/api/api.gyp36
-rw-r--r--extensions/shell/common/api/shell.idl36
-rw-r--r--extensions/shell/common/shell_content_client.cc57
-rw-r--r--extensions/shell/common/shell_content_client.h33
-rw-r--r--extensions/shell/common/shell_extensions_client.cc204
-rw-r--r--extensions/shell/common/shell_extensions_client.h57
-rw-r--r--extensions/shell/common/switches.cc20
-rw-r--r--extensions/shell/common/switches.h20
-rw-r--r--extensions/shell/renderer/DEPS7
-rw-r--r--extensions/shell/renderer/shell_content_renderer_client.cc131
-rw-r--r--extensions/shell/renderer/shell_content_renderer_client.h55
-rw-r--r--extensions/shell/renderer/shell_custom_bindings.cc57
-rw-r--r--extensions/shell/renderer/shell_custom_bindings.h25
-rw-r--r--extensions/shell/renderer/shell_custom_bindings.js78
-rw-r--r--extensions/shell/renderer/shell_dispatcher_delegate.cc35
-rw-r--r--extensions/shell/renderer/shell_dispatcher_delegate.h33
-rw-r--r--extensions/shell/renderer/shell_extensions_renderer_client.cc27
-rw-r--r--extensions/shell/renderer/shell_extensions_renderer_client.h28
-rw-r--r--extensions/shell/renderer/shell_renderer_main_delegate.h30
-rw-r--r--extensions/shell/test/DEPS4
-rw-r--r--extensions/shell/test/shell_test.cc57
-rw-r--r--extensions/shell/test/shell_test.h48
-rw-r--r--extensions/shell/test/shell_test_launcher_delegate.cc27
-rw-r--r--extensions/shell/test/shell_test_launcher_delegate.h23
-rw-r--r--extensions/shell/test/shell_tests_main.cc15
77 files changed, 4912 insertions, 2 deletions
diff --git a/extensions/DEPS b/extensions/DEPS
index 4077a55..f544c73 100644
--- a/extensions/DEPS
+++ b/extensions/DEPS
@@ -1,6 +1,7 @@
include_rules = [
# Do not add Chrome dependencies. Much work went into removing them.
"+components/url_matcher",
+ "-content",
"+content/public/common",
"+content/public/test",
"+crypto",
diff --git a/extensions/renderer/DEPS b/extensions/renderer/DEPS
index 91bcd4b..ab21030 100644
--- a/extensions/renderer/DEPS
+++ b/extensions/renderer/DEPS
@@ -1,6 +1,4 @@
include_rules = [
- "-content",
- "+content/public/common",
"+content/public/renderer",
"+gin",
diff --git a/extensions/shell/DEPS b/extensions/shell/DEPS
new file mode 100644
index 0000000..ffa7287
--- /dev/null
+++ b/extensions/shell/DEPS
@@ -0,0 +1,23 @@
+include_rules = [
+ # The apps module has dependencies on chrome.
+ "-apps",
+ # Individual subdirectories should have their own DEPS that include
+ # their allowed directories.
+ "-extensions/shell",
+ "+extensions/shell/common",
+ "+extensions/shell/test",
+
+ # Do not add dependencies on Chrome. Talk to OWNERS about how to refactor
+ # the code you need to a shared location.
+ "-chrome",
+
+ # Only allow app_shell and extensions resources, not general Chrome ones.
+ "-grit",
+ "+grit/app_shell_resources.h",
+ "+grit/extensions_resources.h",
+
+ # Real DEPS go in subdirectories, for example extensions/shell/browser/DEPS.
+ # Temporary exceptions for app_shell bring-up go here.
+ # TODO(jamescook): Remove these. http://crbug.com/305404
+ "!chrome/browser/chrome_notification_types.h",
+]
diff --git a/extensions/shell/OWNERS b/extensions/shell/OWNERS
new file mode 100644
index 0000000..00a9ff9
--- /dev/null
+++ b/extensions/shell/OWNERS
@@ -0,0 +1,3 @@
+derat@chromium.org
+jamescook@chromium.org
+yoz@chromium.org
diff --git a/extensions/shell/README b/extensions/shell/README
new file mode 100644
index 0000000..25a04d7
--- /dev/null
+++ b/extensions/shell/README
@@ -0,0 +1,13 @@
+# Introduction
+
+app_shell is an experimental project to build a minimal environment like
+content_shell.
+
+The goal is to be able to run a v2 app and supply most of the chrome.* extension
+APIs without running the rest of Chrome.
+
+app_shell is only officially supported on Chrome OS.
+
+# How to run
+
+app_shell --app=/path/to/extension
diff --git a/extensions/shell/app/DEPS b/extensions/shell/app/DEPS
new file mode 100644
index 0000000..b9b52a1
--- /dev/null
+++ b/extensions/shell/app/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ "+extensions/shell",
+ "+chromeos",
+ "+content/public/app",
+ "+content/public/browser",
+ "+sandbox",
+]
diff --git a/extensions/shell/app/README b/extensions/shell/app/README
new file mode 100644
index 0000000..9dbba28
--- /dev/null
+++ b/extensions/shell/app/README
@@ -0,0 +1,5 @@
+"Application support" for the app_shell executable.
+
+This directory has nothing to do with the apps/extensions themselves.
+
+See content/shell/app for a similar example.
diff --git a/extensions/shell/app/shell_main.cc b/extensions/shell/app/shell_main.cc
new file mode 100644
index 0000000..a58ab82
--- /dev/null
+++ b/extensions/shell/app/shell_main.cc
@@ -0,0 +1,32 @@
+// 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 "content/public/app/content_main.h"
+#include "extensions/shell/app/shell_main_delegate.h"
+
+#if defined(OS_WIN)
+#include "content/public/app/startup_helper_win.h"
+#include "sandbox/win/src/sandbox_types.h"
+#endif
+
+#if defined(OS_WIN)
+int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) {
+#else
+int main(int argc, const char** argv) {
+#endif
+ extensions::ShellMainDelegate delegate;
+ content::ContentMainParams params(&delegate);
+
+#if defined(OS_WIN)
+ sandbox::SandboxInterfaceInfo sandbox_info = {0};
+ content::InitializeSandboxInfo(&sandbox_info);
+ params.instance = instance;
+ params.sandbox_info = &sandbox_info;
+#else
+ params.argc = argc;
+ params.argv = argv;
+#endif
+
+ return content::ContentMain(params);
+}
diff --git a/extensions/shell/app/shell_main_delegate.cc b/extensions/shell/app/shell_main_delegate.cc
new file mode 100644
index 0000000..b3b6ceb
--- /dev/null
+++ b/extensions/shell/app/shell_main_delegate.cc
@@ -0,0 +1,109 @@
+// 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 "extensions/shell/app/shell_main_delegate.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "content/public/browser/browser_main_runner.h"
+#include "content/public/common/content_switches.h"
+#include "extensions/common/extension_paths.h"
+#include "extensions/shell/browser/default_shell_browser_main_delegate.h"
+#include "extensions/shell/browser/shell_content_browser_client.h"
+#include "extensions/shell/common/shell_content_client.h"
+#include "extensions/shell/renderer/shell_content_renderer_client.h"
+#include "extensions/shell/renderer/shell_renderer_main_delegate.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/chromeos_paths.h"
+#endif
+
+namespace {
+
+void InitLogging() {
+ base::FilePath log_filename;
+ PathService::Get(base::DIR_EXE, &log_filename);
+ log_filename = log_filename.AppendASCII("app_shell.log");
+ logging::LoggingSettings settings;
+ settings.logging_dest = logging::LOG_TO_ALL;
+ settings.log_file = log_filename.value().c_str();
+ settings.delete_old = logging::DELETE_OLD_LOG_FILE;
+ logging::InitLogging(settings);
+ logging::SetLogItems(true, true, true, true);
+}
+
+} // namespace
+
+namespace extensions {
+
+ShellMainDelegate::ShellMainDelegate() {
+}
+
+ShellMainDelegate::~ShellMainDelegate() {
+}
+
+bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
+ InitLogging();
+ content_client_.reset(new ShellContentClient);
+ SetContentClient(content_client_.get());
+
+#if defined(OS_CHROMEOS)
+ chromeos::RegisterPathProvider();
+#endif
+ extensions::RegisterPathProvider();
+ return false;
+}
+
+void ShellMainDelegate::PreSandboxStartup() {
+ std::string process_type =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessType);
+ if (ProcessNeedsResourceBundle(process_type))
+ InitializeResourceBundle();
+}
+
+content::ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() {
+ browser_client_.reset(CreateShellContentBrowserClient());
+ return browser_client_.get();
+}
+
+content::ContentBrowserClient*
+ShellMainDelegate::CreateShellContentBrowserClient() {
+ return new ShellContentBrowserClient(new DefaultShellBrowserMainDelegate());
+}
+
+content::ContentRendererClient*
+ShellMainDelegate::CreateContentRendererClient() {
+ renderer_client_.reset(
+ new ShellContentRendererClient(CreateShellRendererMainDelegate()));
+ return renderer_client_.get();
+}
+
+scoped_ptr<ShellRendererMainDelegate>
+ShellMainDelegate::CreateShellRendererMainDelegate() {
+ return scoped_ptr<ShellRendererMainDelegate>();
+}
+
+void ShellMainDelegate::InitializeResourceBundle() {
+ base::FilePath pak_dir;
+ PathService::Get(base::DIR_MODULE, &pak_dir);
+ ui::ResourceBundle::InitSharedInstanceWithPakPath(
+ pak_dir.AppendASCII("app_shell.pak"));
+}
+
+// static
+bool ShellMainDelegate::ProcessNeedsResourceBundle(
+ const std::string& process_type) {
+ // The browser process has no process type flag, but needs resources.
+ // On Linux the zygote process opens the resources for the renderers.
+ return process_type.empty() ||
+ process_type == switches::kZygoteProcess ||
+ process_type == switches::kRendererProcess ||
+ process_type == switches::kUtilityProcess;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/app/shell_main_delegate.h b/extensions/shell/app/shell_main_delegate.h
new file mode 100644
index 0000000..7e120f4
--- /dev/null
+++ b/extensions/shell/app/shell_main_delegate.h
@@ -0,0 +1,60 @@
+// 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 EXTENSIONS_SHELL_APP_SHELL_MAIN_DELEGATE_H_
+#define EXTENSIONS_SHELL_APP_SHELL_MAIN_DELEGATE_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/app/content_main_delegate.h"
+
+namespace content {
+class BrowserContext;
+class ContentBrowserClient;
+class ContentClient;
+class ContentRendererClient;
+}
+
+namespace extensions {
+class ShellBrowserMainDelegate;
+class ShellRendererMainDelegate;
+
+class ShellMainDelegate : public content::ContentMainDelegate {
+ public:
+ ShellMainDelegate();
+ virtual ~ShellMainDelegate();
+
+ // ContentMainDelegate implementation:
+ virtual bool BasicStartupComplete(int* exit_code) OVERRIDE;
+ virtual void PreSandboxStartup() OVERRIDE;
+ virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
+ virtual content::ContentRendererClient* CreateContentRendererClient()
+ OVERRIDE;
+
+ protected:
+ // The created object is owned by this object.
+ virtual content::ContentBrowserClient* CreateShellContentBrowserClient();
+
+ // The returned object is owned by ShellContentRendererClient.
+ virtual scoped_ptr<ShellRendererMainDelegate>
+ CreateShellRendererMainDelegate();
+
+ // Initializes the resource bundle and resources.pak.
+ virtual void InitializeResourceBundle();
+
+ private:
+ // |process_type| is zygote, renderer, utility, etc. Returns true if the
+ // process needs data from resources.pak.
+ static bool ProcessNeedsResourceBundle(const std::string& process_type);
+
+ scoped_ptr<content::ContentClient> content_client_;
+ scoped_ptr<content::ContentBrowserClient> browser_client_;
+ scoped_ptr<content::ContentRendererClient> renderer_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellMainDelegate);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_APP_SHELL_MAIN_DELEGATE_H_
diff --git a/extensions/shell/app_shell.gyp b/extensions/shell/app_shell.gyp
new file mode 100644
index 0000000..d95b385
--- /dev/null
+++ b/extensions/shell/app_shell.gyp
@@ -0,0 +1,223 @@
+# 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'app_shell_resources',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'generate_app_shell_resources',
+ 'variables': {
+ 'grit_grd_file': 'app_shell_resources.grd',
+ 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/extensions/shell',
+ },
+ 'includes': [ '../../build/grit_action.gypi' ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'app_shell_pak',
+ 'type': 'none',
+ 'dependencies': [
+ 'app_shell_resources',
+ # Need extension related resources in common_resources.pak and
+ # renderer_resources_100_percent.pak
+ '<(DEPTH)/chrome/chrome_resources.gyp:chrome_resources',
+ # Need dev-tools related resources in shell_resources.pak and
+ # devtools_resources.pak.
+ '<(DEPTH)/content/content_shell_and_tests.gyp:content_shell_resources',
+ '<(DEPTH)/content/browser/devtools/devtools_resources.gyp:devtools_resources',
+ '<(DEPTH)/extensions/extensions_resources.gyp:extensions_resources',
+ '<(DEPTH)/extensions/extensions_strings.gyp:extensions_strings',
+ '<(DEPTH)/ui/resources/ui_resources.gyp:ui_resources',
+ '<(DEPTH)/ui/strings/ui_strings.gyp:ui_strings',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'repack_app_shell_pack',
+ 'variables': {
+ 'pak_inputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/chrome/common_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/chrome/extensions_api_resources.pak',
+ # TODO(jamescook): Extract the extension/app related resources
+ # from generated_resources_en-US.pak.
+ '<(SHARED_INTERMEDIATE_DIR)/chrome/generated_resources_en-US.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/chrome/renderer_resources_100_percent.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/content/shell_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/extensions/extensions_renderer_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/extensions/extensions_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/extensions/shell/app_shell_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/extensions/strings/extensions_strings_en-US.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/resources/ui_resources_100_percent.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/strings/app_locale_settings_en-US.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/strings/ui_strings_en-US.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak',
+ ],
+ 'pak_output': '<(PRODUCT_DIR)/app_shell.pak',
+ },
+ 'includes': [ '../../build/repack_action.gypi' ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'app_shell_lib',
+ 'type': 'static_library',
+ 'defines!': ['CONTENT_IMPLEMENTATION'],
+ 'dependencies': [
+ 'app_shell_pak',
+ '<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/base/base.gyp:base_prefs_test_support',
+ '<(DEPTH)/components/components.gyp:omaha_query_params',
+ '<(DEPTH)/components/components.gyp:pref_registry',
+ '<(DEPTH)/components/components.gyp:user_prefs',
+ '<(DEPTH)/content/content.gyp:content',
+ '<(DEPTH)/content/content.gyp:content_gpu',
+ '<(DEPTH)/content/content.gyp:content_ppapi_plugin',
+ '<(DEPTH)/content/content.gyp:content_worker',
+ '<(DEPTH)/content/content_shell_and_tests.gyp:content_shell_lib',
+ '<(DEPTH)/extensions/common/api/api.gyp:extensions_api',
+ '<(DEPTH)/extensions/extensions.gyp:extensions_browser',
+ '<(DEPTH)/extensions/extensions.gyp:extensions_common',
+ '<(DEPTH)/extensions/extensions.gyp:extensions_renderer',
+ '<(DEPTH)/extensions/extensions_resources.gyp:extensions_resources',
+ '<(DEPTH)/extensions/shell/common/api/api.gyp:shell_api',
+ '<(DEPTH)/mojo/mojo.gyp:mojo_environment_chromium',
+ '<(DEPTH)/mojo/mojo.gyp:mojo_system_impl',
+ '<(DEPTH)/skia/skia.gyp:skia',
+ '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
+ '<(DEPTH)/ui/wm/wm.gyp:wm',
+ '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
+ ],
+ 'include_dirs': [
+ '../..',
+ '<(SHARED_INTERMEDIATE_DIR)',
+ '<(SHARED_INTERMEDIATE_DIR)/extensions/shell',
+ ],
+ 'sources': [
+ 'app/shell_main_delegate.cc',
+ 'app/shell_main_delegate.h',
+ 'browser/api/shell/shell_api.cc',
+ 'browser/api/shell/shell_api.h',
+ 'browser/default_shell_browser_main_delegate.cc',
+ 'browser/default_shell_browser_main_delegate.h',
+ 'browser/default_shell_app_window_controller.cc',
+ 'browser/default_shell_app_window_controller.h',
+ 'browser/shell_app_sorting.cc',
+ 'browser/shell_app_sorting.h',
+ 'browser/shell_app_window.cc',
+ 'browser/shell_app_window.h',
+ 'browser/shell_app_window_controller.h',
+ 'browser/shell_browser_context.cc',
+ 'browser/shell_browser_context.h',
+ 'browser/shell_browser_main_delegate.h',
+ 'browser/shell_browser_main_parts.cc',
+ 'browser/shell_browser_main_parts.h',
+ 'browser/shell_content_browser_client.cc',
+ 'browser/shell_content_browser_client.h',
+ 'browser/shell_desktop_controller.cc',
+ 'browser/shell_desktop_controller.h',
+ 'browser/shell_extension_system.cc',
+ 'browser/shell_extension_system.h',
+ 'browser/shell_extension_system_factory.cc',
+ 'browser/shell_extension_system_factory.h',
+ 'browser/shell_extension_web_contents_observer.cc',
+ 'browser/shell_extension_web_contents_observer.h',
+ 'browser/shell_extensions_browser_client.cc',
+ 'browser/shell_extensions_browser_client.h',
+ 'browser/shell_network_controller_chromeos.cc',
+ 'browser/shell_network_controller_chromeos.h',
+ 'browser/shell_omaha_query_params_delegate.cc',
+ 'browser/shell_omaha_query_params_delegate.h',
+ 'browser/shell_runtime_api_delegate.cc',
+ 'browser/shell_runtime_api_delegate.h',
+ 'browser/shell_special_storage_policy.cc',
+ 'browser/shell_special_storage_policy.h',
+ 'common/shell_content_client.cc',
+ 'common/shell_content_client.h',
+ 'common/shell_extensions_client.cc',
+ 'common/shell_extensions_client.h',
+ 'common/switches.h',
+ 'common/switches.cc',
+ 'renderer/shell_content_renderer_client.cc',
+ 'renderer/shell_content_renderer_client.h',
+ 'renderer/shell_custom_bindings.cc',
+ 'renderer/shell_custom_bindings.h',
+ 'renderer/shell_custom_bindings.js',
+ 'renderer/shell_dispatcher_delegate.cc',
+ 'renderer/shell_dispatcher_delegate.h',
+ 'renderer/shell_extensions_renderer_client.cc',
+ 'renderer/shell_extensions_renderer_client.h',
+ 'renderer/shell_renderer_main_delegate.h',
+ ],
+ 'conditions': [
+ ['chromeos==1', {
+ 'dependencies': [
+ '<(DEPTH)/chromeos/chromeos.gyp:chromeos',
+ '<(DEPTH)/ui/chromeos/ui_chromeos.gyp:ui_chromeos',
+ '<(DEPTH)/ui/display/display.gyp:display',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'app_shell',
+ 'type': 'executable',
+ 'defines!': ['CONTENT_IMPLEMENTATION'],
+ 'dependencies': [
+ 'app_shell_lib',
+ 'app_shell_pak',
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ 'sources': [
+ 'app/shell_main.cc',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ 'dependencies': [
+ '<(DEPTH)/sandbox/sandbox.gyp:sandbox',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'app_shell_browsertests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'app_shell_lib',
+ # TODO(yoz): find the right deps
+ '<(DEPTH)/base/base.gyp:test_support_base',
+ '<(DEPTH)/content/content.gyp:content_app_both',
+ '<(DEPTH)/content/content_shell_and_tests.gyp:content_browser_test_support',
+ '<(DEPTH)/content/content_shell_and_tests.gyp:test_support_content',
+ '<(DEPTH)/extensions/extensions.gyp:extensions_test_support',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ ],
+ 'defines': [
+ 'HAS_OUT_OF_PROC_TEST_RUNNER',
+ ],
+ 'sources': [
+ # TODO(yoz): Refactor once we have a second test target.
+ 'browser/dns_apitest.cc',
+ 'browser/shell_browsertest.cc',
+ 'test/shell_test.h',
+ 'test/shell_test.cc',
+ 'test/shell_test_launcher_delegate.cc',
+ 'test/shell_test_launcher_delegate.h',
+ 'test/shell_tests_main.cc',
+ ],
+ },
+ ], # targets
+}
diff --git a/extensions/shell/app_shell_resources.grd b/extensions/shell/app_shell_resources.grd
new file mode 100644
index 0000000..236b488
--- /dev/null
+++ b/extensions/shell/app_shell_resources.grd
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1">
+ <outputs>
+ <output filename="grit/app_shell_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="app_shell_resources.pak" type="data_package" />
+ </outputs>
+ <release seq="1">
+ <includes>
+ <!-- Features specific to app_shell. -->
+ <include name="IDR_SHELL_EXTENSION_API_FEATURES" file="common\api\_api_features.json" type="BINDATA" />
+
+ <!-- Custom bindings for extension APIs. -->
+ <include name="IDR_SHELL_CUSTOM_BINDINGS_JS" file="renderer\shell_custom_bindings.js" type="BINDATA" />
+ </includes>
+ </release>
+</grit>
diff --git a/extensions/shell/browser/DEPS b/extensions/shell/browser/DEPS
new file mode 100644
index 0000000..edfa2580
--- /dev/null
+++ b/extensions/shell/browser/DEPS
@@ -0,0 +1,25 @@
+include_rules = [
+ "+chromeos",
+ "+components/keyed_service",
+ "+components/omaha_query_params",
+ "+components/pref_registry",
+ "+components/user_prefs",
+ "+content/public/browser",
+ "+third_party/cros_system_api",
+
+ # Pieces of content_shell reused in app_shell.
+ "+content/shell/browser/shell_browser_context.h",
+ "+content/shell/browser/shell_devtools_delegate.h",
+ "+content/shell/browser/shell_net_log.h",
+
+ # Only used in API tests that should be moved to extensions/browser/api/...
+ "+net",
+
+ "+sync/api",
+
+ # Disallow views to keep the binary size down.
+ "-ui/views",
+
+ "-webkit",
+ "+webkit/browser/quota",
+]
diff --git a/extensions/shell/browser/api/shell/shell_api.cc b/extensions/shell/browser/api/shell/shell_api.cc
new file mode 100644
index 0000000..c022f16
--- /dev/null
+++ b/extensions/shell/browser/api/shell/shell_api.cc
@@ -0,0 +1,59 @@
+// 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 "extensions/shell/browser/api/shell/shell_api.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "extensions/common/extension.h"
+#include "extensions/shell/browser/shell_app_window.h"
+#include "extensions/shell/browser/shell_desktop_controller.h"
+#include "extensions/shell/common/api/shell.h"
+
+using base::DictionaryValue;
+
+namespace CreateWindow = extensions::shell_api::shell::CreateWindow;
+
+namespace extensions {
+
+namespace {
+
+const char kInvalidArguments[] = "Invalid arguments";
+
+// Creates a function call result to send to the renderer.
+DictionaryValue* CreateResult(ShellAppWindow* app_window) {
+ int view_id = app_window->GetRenderViewRoutingID();
+
+ DictionaryValue* result = new DictionaryValue;
+ result->Set("viewId", new base::FundamentalValue(view_id));
+ return result;
+}
+
+} // namespace
+
+ShellCreateWindowFunction::ShellCreateWindowFunction() {
+}
+
+ShellCreateWindowFunction::~ShellCreateWindowFunction() {
+}
+
+ExtensionFunction::ResponseAction ShellCreateWindowFunction::Run() {
+ scoped_ptr<CreateWindow::Params> params(CreateWindow::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ // Convert "main.html" to "chrome-extension:/<id>/main.html".
+ GURL url = GetExtension()->GetResourceURL(params->url);
+ if (!url.is_valid())
+ return RespondNow(Error(kInvalidArguments));
+
+ // The desktop keeps ownership of the window.
+ ShellAppWindow* app_window =
+ ShellDesktopController::instance()->CreateAppWindow(browser_context());
+ app_window->LoadURL(url);
+
+ // Create the reply to send to the renderer.
+ return RespondNow(OneArgument(CreateResult(app_window)));
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/api/shell/shell_api.h b/extensions/shell/browser/api/shell/shell_api.h
new file mode 100644
index 0000000..fab9380
--- /dev/null
+++ b/extensions/shell/browser/api/shell/shell_api.h
@@ -0,0 +1,33 @@
+// 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 EXTENSIONS_SHELL_BROWSER_API_SHELL_SHELL_API_H_
+#define EXTENSIONS_SHELL_BROWSER_API_SHELL_SHELL_API_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "extensions/browser/extension_function.h"
+#include "extensions/browser/extension_function_histogram_value.h"
+
+namespace extensions {
+
+// Implementation of the chrome.shell.createWindow() function for app_shell.
+// Opens a fullscreen window and invokes the window callback to allow access to
+// the JS contentWindow.
+class ShellCreateWindowFunction : public UIThreadExtensionFunction {
+ public:
+ ShellCreateWindowFunction();
+
+ DECLARE_EXTENSION_FUNCTION("shell.createWindow", SHELL_CREATEWINDOW);
+
+ private:
+ virtual ~ShellCreateWindowFunction();
+ virtual ResponseAction Run() OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellCreateWindowFunction);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_API_SHELL_SHELL_API_H_
diff --git a/extensions/shell/browser/default_shell_app_window_controller.cc b/extensions/shell/browser/default_shell_app_window_controller.cc
new file mode 100644
index 0000000..778bc09
--- /dev/null
+++ b/extensions/shell/browser/default_shell_app_window_controller.cc
@@ -0,0 +1,45 @@
+// 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 "extensions/shell/browser/default_shell_app_window_controller.h"
+
+#include "base/logging.h"
+#include "extensions/shell/browser/shell_app_window.h"
+#include "extensions/shell/browser/shell_desktop_controller.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+
+namespace extensions {
+
+DefaultShellAppWindowController::DefaultShellAppWindowController(
+ ShellDesktopController* shell_desktop_controller)
+ : shell_desktop_controller_(shell_desktop_controller) {
+ DCHECK(shell_desktop_controller_);
+}
+
+DefaultShellAppWindowController::~DefaultShellAppWindowController() {
+ // The app window must be explicitly closed before desktop teardown.
+ DCHECK(!app_window_);
+}
+
+ShellAppWindow* DefaultShellAppWindowController::CreateAppWindow(
+ content::BrowserContext* context) {
+ aura::Window* root_window = shell_desktop_controller_->host()->window();
+
+ app_window_.reset(new ShellAppWindow);
+ app_window_->Init(context, root_window->bounds().size());
+
+ // Attach the web contents view to our window hierarchy.
+ aura::Window* content = app_window_->GetNativeWindow();
+ root_window->AddChild(content);
+ content->Show();
+
+ return app_window_.get();
+}
+
+void DefaultShellAppWindowController::CloseAppWindows() {
+ app_window_.reset();
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/default_shell_app_window_controller.h b/extensions/shell/browser/default_shell_app_window_controller.h
new file mode 100644
index 0000000..558022c2c
--- /dev/null
+++ b/extensions/shell/browser/default_shell_app_window_controller.h
@@ -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.
+
+#ifndef EXTENSIONS_SHELL_BROWSER_DEFAULT_SHELL_APP_WINDOW_CONTROLLER_H_
+#define EXTENSIONS_SHELL_BROWSER_DEFAULT_SHELL_APP_WINDOW_CONTROLLER_H_
+
+#include "extensions/shell/browser/shell_app_window_controller.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace extensions {
+
+class ShellDesktopController;
+
+// The default shell app window controller for app_shell. It manages only one
+// app_window.
+class DefaultShellAppWindowController : public ShellAppWindowController {
+ public:
+ explicit DefaultShellAppWindowController(
+ ShellDesktopController* shell_desktop_controller);
+ virtual ~DefaultShellAppWindowController();
+
+ // ShellAppWindowController implementation.
+ virtual ShellAppWindow* CreateAppWindow(
+ content::BrowserContext* context) OVERRIDE;
+ virtual void CloseAppWindows() OVERRIDE;
+
+ private:
+ ShellDesktopController* shell_desktop_controller_; // Not owned
+
+ // The desktop supports a single app window.
+ scoped_ptr<ShellAppWindow> app_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultShellAppWindowController);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_DEFAULT_SHELL_APP_WINDOW_CONTROLLER_H_
diff --git a/extensions/shell/browser/default_shell_browser_main_delegate.cc b/extensions/shell/browser/default_shell_browser_main_delegate.cc
new file mode 100644
index 0000000..5fb2cf1
--- /dev/null
+++ b/extensions/shell/browser/default_shell_browser_main_delegate.cc
@@ -0,0 +1,52 @@
+// 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 "extensions/shell/browser/default_shell_browser_main_delegate.h"
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "extensions/shell/browser/default_shell_app_window_controller.h"
+#include "extensions/shell/browser/shell_desktop_controller.h"
+#include "extensions/shell/browser/shell_extension_system.h"
+#include "extensions/shell/common/switches.h"
+
+namespace extensions {
+
+DefaultShellBrowserMainDelegate::DefaultShellBrowserMainDelegate() {
+}
+
+DefaultShellBrowserMainDelegate::~DefaultShellBrowserMainDelegate() {
+}
+
+void DefaultShellBrowserMainDelegate::Start(
+ content::BrowserContext* browser_context) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kAppShellAppPath)) {
+ base::FilePath app_dir(
+ command_line->GetSwitchValueNative(switches::kAppShellAppPath));
+ base::FilePath app_absolute_dir = base::MakeAbsoluteFilePath(app_dir);
+
+ ShellExtensionSystem* extension_system = static_cast<ShellExtensionSystem*>(
+ ExtensionSystem::Get(browser_context));
+ if (!extension_system->LoadApp(app_absolute_dir))
+ return;
+ extension_system->LaunchApp();
+ } else {
+ LOG(ERROR) << "--" << switches::kAppShellAppPath
+ << " unset; boredom is in your future";
+ }
+}
+
+void DefaultShellBrowserMainDelegate::Shutdown() {
+}
+
+ShellDesktopController*
+DefaultShellBrowserMainDelegate::CreateDesktopController() {
+ ShellDesktopController* desktop = new ShellDesktopController();
+ desktop->SetAppWindowController(new DefaultShellAppWindowController(desktop));
+ return desktop;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/default_shell_browser_main_delegate.h b/extensions/shell/browser/default_shell_browser_main_delegate.h
new file mode 100644
index 0000000..a59c2e4
--- /dev/null
+++ b/extensions/shell/browser/default_shell_browser_main_delegate.h
@@ -0,0 +1,32 @@
+// 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 EXTENSIONS_SHELL_BROWSER_DEFAULT_SHELL_BROWSER_MAIN_DELEGATE_H_
+#define EXTENSIONS_SHELL_BROWSER_DEFAULT_SHELL_BROWSER_MAIN_DELEGATE_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "extensions/shell/browser/shell_browser_main_delegate.h"
+
+namespace extensions {
+
+// A ShellBrowserMainDelegate that starts an application specified
+// by the "--app" command line. This is used only in the browser process.
+class DefaultShellBrowserMainDelegate : public ShellBrowserMainDelegate {
+ public:
+ DefaultShellBrowserMainDelegate();
+ virtual ~DefaultShellBrowserMainDelegate();
+
+ // ShellBrowserMainDelegate:
+ virtual void Start(content::BrowserContext* context) OVERRIDE;
+ virtual void Shutdown() OVERRIDE;
+ virtual ShellDesktopController* CreateDesktopController() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DefaultShellBrowserMainDelegate);
+};
+
+} // namespace extensions
+
+#endif // DEFAULT_SHELL_BROWSER_MAIN_DELEGATE_H_
diff --git a/extensions/shell/browser/dns_apitest.cc b/extensions/shell/browser/dns_apitest.cc
new file mode 100644
index 0000000..fa2ec2f
--- /dev/null
+++ b/extensions/shell/browser/dns_apitest.cc
@@ -0,0 +1,128 @@
+// 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 "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "extensions/browser/api/dns/dns_api.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
+#include "extensions/browser/api/dns/mock_host_resolver_creator.h"
+#include "extensions/browser/api_test_utils.h"
+#include "extensions/browser/extension_function_dispatcher.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/shell/test/shell_test.h"
+#include "net/base/net_errors.h"
+
+using extensions::api_test_utils::RunFunctionAndReturnSingleResult;
+
+namespace extensions {
+
+namespace {
+
+class TestFunctionDispatcherDelegate
+ : public ExtensionFunctionDispatcher::Delegate {
+ public:
+ TestFunctionDispatcherDelegate() {}
+ virtual ~TestFunctionDispatcherDelegate() {}
+
+ // NULL implementation.
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestFunctionDispatcherDelegate);
+};
+
+} // namespace
+
+class DnsApiTest : public AppShellTest {
+ public:
+ DnsApiTest() : resolver_creator_(new MockHostResolverCreator()) {}
+
+ private:
+ virtual void SetUpOnMainThread() OVERRIDE {
+ AppShellTest::SetUpOnMainThread();
+ HostResolverWrapper::GetInstance()->SetHostResolverForTesting(
+ resolver_creator_->CreateMockHostResolver());
+ }
+
+ virtual void TearDownOnMainThread() OVERRIDE {
+ HostResolverWrapper::GetInstance()->SetHostResolverForTesting(NULL);
+ resolver_creator_->DeleteMockHostResolver();
+ AppShellTest::TearDownOnMainThread();
+ }
+
+ // The MockHostResolver asserts that it's used on the same thread on which
+ // it's created, which is actually a stronger rule than its real counterpart.
+ // But that's fine; it's good practice.
+ scoped_refptr<MockHostResolverCreator> resolver_creator_;
+};
+
+IN_PROC_BROWSER_TEST_F(DnsApiTest, DnsResolveIPLiteral) {
+ scoped_refptr<DnsResolveFunction> resolve_function(new DnsResolveFunction());
+ scoped_refptr<Extension> empty_extension(
+ ExtensionBuilder()
+ .SetManifest(
+ DictionaryBuilder().Set("name", "Test").Set("version", "1.0"))
+ .Build());
+
+ resolve_function->set_extension(empty_extension.get());
+ resolve_function->set_has_callback(true);
+
+ TestFunctionDispatcherDelegate delegate;
+ scoped_ptr<ExtensionFunctionDispatcher> dispatcher(
+ new ExtensionFunctionDispatcher(browser_context(), &delegate));
+
+ scoped_ptr<base::Value> result(
+ RunFunctionAndReturnSingleResult(resolve_function.get(),
+ "[\"127.0.0.1\"]",
+ browser_context(),
+ dispatcher.Pass()));
+ base::DictionaryValue* dict = NULL;
+ ASSERT_TRUE(result->GetAsDictionary(&dict));
+
+ int result_code = 0;
+ EXPECT_TRUE(dict->GetInteger("resultCode", &result_code));
+ EXPECT_EQ(net::OK, result_code);
+
+ std::string address;
+ EXPECT_TRUE(dict->GetString("address", &address));
+ EXPECT_EQ("127.0.0.1", address);
+}
+
+IN_PROC_BROWSER_TEST_F(DnsApiTest, DnsResolveHostname) {
+ scoped_refptr<DnsResolveFunction> resolve_function(new DnsResolveFunction());
+ scoped_refptr<Extension> empty_extension(
+ ExtensionBuilder()
+ .SetManifest(
+ DictionaryBuilder().Set("name", "Test").Set("version", "1.0"))
+ .Build());
+
+ resolve_function->set_extension(empty_extension.get());
+ resolve_function->set_has_callback(true);
+
+ TestFunctionDispatcherDelegate delegate;
+ scoped_ptr<ExtensionFunctionDispatcher> dispatcher(
+ new ExtensionFunctionDispatcher(browser_context(), &delegate));
+
+ std::string function_arguments("[\"");
+ function_arguments += MockHostResolverCreator::kHostname;
+ function_arguments += "\"]";
+ scoped_ptr<base::Value> result(
+ RunFunctionAndReturnSingleResult(resolve_function.get(),
+ function_arguments,
+ browser_context(),
+ dispatcher.Pass()));
+ base::DictionaryValue* dict = NULL;
+ ASSERT_TRUE(result->GetAsDictionary(&dict));
+
+ int result_code = 0;
+ EXPECT_TRUE(dict->GetInteger("resultCode", &result_code));
+ EXPECT_EQ(net::OK, result_code);
+
+ std::string address;
+ EXPECT_TRUE(dict->GetString("address", &address));
+ EXPECT_EQ(MockHostResolverCreator::kAddress, address);
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_app_sorting.cc b/extensions/shell/browser/shell_app_sorting.cc
new file mode 100644
index 0000000..146de59
--- /dev/null
+++ b/extensions/shell/browser/shell_app_sorting.cc
@@ -0,0 +1,105 @@
+// 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 "extensions/shell/browser/shell_app_sorting.h"
+
+#include "sync/api/string_ordinal.h"
+
+namespace {
+
+// Ordinals for a single app on a single page.
+const char kFirstApp[] = "a";
+const char kNextApp[] = "b";
+const char kFirstPage[] = "a";
+
+} // namespace
+
+namespace extensions {
+
+ShellAppSorting::ShellAppSorting() {
+}
+
+ShellAppSorting::~ShellAppSorting() {
+}
+
+void ShellAppSorting::SetExtensionScopedPrefs(ExtensionScopedPrefs* prefs) {
+}
+
+void ShellAppSorting::SetExtensionSyncService(
+ ExtensionSyncService* extension_sync_service) {
+}
+
+void ShellAppSorting::Initialize(const ExtensionIdList& extension_ids) {
+}
+
+void ShellAppSorting::FixNTPOrdinalCollisions() {
+}
+
+void ShellAppSorting::EnsureValidOrdinals(
+ const std::string& extension_id,
+ const syncer::StringOrdinal& suggested_page) {
+}
+
+void ShellAppSorting::OnExtensionMoved(
+ const std::string& moved_extension_id,
+ const std::string& predecessor_extension_id,
+ const std::string& successor_extension_id) {
+}
+
+syncer::StringOrdinal ShellAppSorting::GetAppLaunchOrdinal(
+ const std::string& extension_id) const {
+ return syncer::StringOrdinal(kFirstApp);
+}
+
+void ShellAppSorting::SetAppLaunchOrdinal(
+ const std::string& extension_id,
+ const syncer::StringOrdinal& new_app_launch_ordinal) {
+}
+
+syncer::StringOrdinal ShellAppSorting::CreateFirstAppLaunchOrdinal(
+ const syncer::StringOrdinal& page_ordinal) const {
+ return syncer::StringOrdinal(kFirstApp);
+}
+
+syncer::StringOrdinal ShellAppSorting::CreateNextAppLaunchOrdinal(
+ const syncer::StringOrdinal& page_ordinal) const {
+ return syncer::StringOrdinal(kNextApp);
+}
+
+syncer::StringOrdinal ShellAppSorting::CreateFirstAppPageOrdinal() const {
+ return syncer::StringOrdinal(kFirstPage);
+}
+
+syncer::StringOrdinal ShellAppSorting::GetNaturalAppPageOrdinal() const {
+ return syncer::StringOrdinal(kFirstPage);
+}
+
+syncer::StringOrdinal ShellAppSorting::GetPageOrdinal(
+ const std::string& extension_id) const {
+ return syncer::StringOrdinal(kFirstPage);
+}
+
+void ShellAppSorting::SetPageOrdinal(
+ const std::string& extension_id,
+ const syncer::StringOrdinal& new_page_ordinal) {
+}
+
+void ShellAppSorting::ClearOrdinals(const std::string& extension_id) {
+}
+
+int ShellAppSorting::PageStringOrdinalAsInteger(
+ const syncer::StringOrdinal& page_ordinal) const {
+ return 0;
+}
+
+syncer::StringOrdinal ShellAppSorting::PageIntegerAsStringOrdinal(
+ size_t page_index) {
+ return syncer::StringOrdinal(kFirstPage);
+}
+
+void ShellAppSorting::SetExtensionVisible(const std::string& extension_id,
+ bool visible) {
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_app_sorting.h b/extensions/shell/browser/shell_app_sorting.h
new file mode 100644
index 0000000..b0dac33
--- /dev/null
+++ b/extensions/shell/browser/shell_app_sorting.h
@@ -0,0 +1,63 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_APP_SORTING_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_APP_SORTING_H_
+
+#include "base/compiler_specific.h"
+#include "extensions/browser/app_sorting.h"
+
+namespace extensions {
+
+// A stub AppSorting. Since app_shell only runs a single app we don't need to
+// sort them.
+class ShellAppSorting : public AppSorting {
+ public:
+ ShellAppSorting();
+ virtual ~ShellAppSorting();
+
+ // AppSorting overrides:
+ virtual void SetExtensionScopedPrefs(ExtensionScopedPrefs* prefs) OVERRIDE;
+ virtual void SetExtensionSyncService(
+ ExtensionSyncService* extension_sync_service) OVERRIDE;
+ virtual void Initialize(const ExtensionIdList& extension_ids) OVERRIDE;
+ virtual void FixNTPOrdinalCollisions() OVERRIDE;
+ virtual void EnsureValidOrdinals(
+ const std::string& extension_id,
+ const syncer::StringOrdinal& suggested_page) OVERRIDE;
+ virtual void OnExtensionMoved(
+ const std::string& moved_extension_id,
+ const std::string& predecessor_extension_id,
+ const std::string& successor_extension_id) OVERRIDE;
+ virtual syncer::StringOrdinal GetAppLaunchOrdinal(
+ const std::string& extension_id) const OVERRIDE;
+ virtual void SetAppLaunchOrdinal(
+ const std::string& extension_id,
+ const syncer::StringOrdinal& new_app_launch_ordinal) OVERRIDE;
+ virtual syncer::StringOrdinal CreateFirstAppLaunchOrdinal(
+ const syncer::StringOrdinal& page_ordinal) const OVERRIDE;
+ virtual syncer::StringOrdinal CreateNextAppLaunchOrdinal(
+ const syncer::StringOrdinal& page_ordinal) const OVERRIDE;
+ virtual syncer::StringOrdinal CreateFirstAppPageOrdinal() const OVERRIDE;
+ virtual syncer::StringOrdinal GetNaturalAppPageOrdinal() const OVERRIDE;
+ virtual syncer::StringOrdinal GetPageOrdinal(
+ const std::string& extension_id) const OVERRIDE;
+ virtual void SetPageOrdinal(
+ const std::string& extension_id,
+ const syncer::StringOrdinal& new_page_ordinal) OVERRIDE;
+ virtual void ClearOrdinals(const std::string& extension_id) OVERRIDE;
+ virtual int PageStringOrdinalAsInteger(
+ const syncer::StringOrdinal& page_ordinal) const OVERRIDE;
+ virtual syncer::StringOrdinal PageIntegerAsStringOrdinal(
+ size_t page_index) OVERRIDE;
+ virtual void SetExtensionVisible(const std::string& extension_id,
+ bool visible) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellAppSorting);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_APP_SORTING_H_
diff --git a/extensions/shell/browser/shell_app_window.cc b/extensions/shell/browser/shell_app_window.cc
new file mode 100644
index 0000000..a66554e
--- /dev/null
+++ b/extensions/shell/browser/shell_app_window.cc
@@ -0,0 +1,75 @@
+// 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 "extensions/shell/browser/shell_app_window.h"
+
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/view_type_utils.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/shell/browser/shell_extension_web_contents_observer.h"
+#include "ipc/ipc_message_macros.h"
+
+using content::BrowserContext;
+using content::WebContents;
+
+namespace extensions {
+
+ShellAppWindow::ShellAppWindow() {
+}
+
+ShellAppWindow::~ShellAppWindow() {
+}
+
+void ShellAppWindow::Init(BrowserContext* context, gfx::Size initial_size) {
+ extension_function_dispatcher_.reset(
+ new ExtensionFunctionDispatcher(context, this));
+
+ // Create the web contents with an initial size to avoid a resize.
+ WebContents::CreateParams create_params(context);
+ create_params.initial_size = initial_size;
+ web_contents_.reset(WebContents::Create(create_params));
+
+ content::WebContentsObserver::Observe(web_contents_.get());
+
+ // Add support for extension startup.
+ ShellExtensionWebContentsObserver::CreateForWebContents(web_contents_.get());
+
+ SetViewType(web_contents_.get(), VIEW_TYPE_APP_WINDOW);
+}
+
+void ShellAppWindow::LoadURL(const GURL& url) {
+ content::NavigationController::LoadURLParams params(url);
+ web_contents_->GetController().LoadURLWithParams(params);
+ web_contents_->Focus();
+}
+
+aura::Window* ShellAppWindow::GetNativeWindow() {
+ return web_contents_->GetNativeView();
+}
+
+int ShellAppWindow::GetRenderViewRoutingID() {
+ return web_contents_->GetRenderViewHost()->GetRoutingID();
+}
+
+bool ShellAppWindow::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ShellAppWindow, message)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+content::WebContents* ShellAppWindow::GetAssociatedWebContents() const {
+ return web_contents_.get();
+}
+
+void ShellAppWindow::OnRequest(const ExtensionHostMsg_Request_Params& params) {
+ extension_function_dispatcher_->Dispatch(params,
+ web_contents_->GetRenderViewHost());
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_app_window.h b/extensions/shell/browser/shell_app_window.h
new file mode 100644
index 0000000..d85f4f0
--- /dev/null
+++ b/extensions/shell/browser/shell_app_window.h
@@ -0,0 +1,72 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_APP_WINDOW_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_APP_WINDOW_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "extensions/browser/extension_function_dispatcher.h"
+
+struct ExtensionHostMsg_Request_Params;
+class GURL;
+
+namespace aura {
+class Window;
+}
+
+namespace content {
+class BrowserContext;
+class WebContents;
+}
+
+namespace gfx {
+class Size;
+}
+
+namespace extensions {
+
+class ExtensionFunctionDispatcher;
+
+// A simplified app window created by chrome.app.window.create(). Manages the
+// primary web contents for the app.
+class ShellAppWindow : public content::WebContentsObserver,
+ public ExtensionFunctionDispatcher::Delegate {
+ public:
+ ShellAppWindow();
+ virtual ~ShellAppWindow();
+
+ // Creates the web contents and attaches extension-specific helpers.
+ // Passing a valid |initial_size| to avoid a web contents resize.
+ void Init(content::BrowserContext* context, gfx::Size initial_size);
+
+ // Starts loading |url| which must be an extension URL.
+ void LoadURL(const GURL& url);
+
+ // Returns the window hosting the web contents.
+ aura::Window* GetNativeWindow();
+
+ // Returns the routing ID of the render view host of |web_contents_|.
+ int GetRenderViewRoutingID();
+
+ // content::WebContentsObserver implementation
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // ExtensionFunctionDispatcher::Delegate implementation
+ virtual content::WebContents* GetAssociatedWebContents() const OVERRIDE;
+
+ private:
+ // IPC handler.
+ void OnRequest(const ExtensionHostMsg_Request_Params& params);
+
+ scoped_ptr<content::WebContents> web_contents_;
+ scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellAppWindow);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_APP_WINDOW_H_
diff --git a/extensions/shell/browser/shell_app_window_controller.h b/extensions/shell/browser/shell_app_window_controller.h
new file mode 100644
index 0000000..f8a7fa0
--- /dev/null
+++ b/extensions/shell/browser/shell_app_window_controller.h
@@ -0,0 +1,30 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_APP_WINDOW_CONTROLLER_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_APP_WINDOW_CONTROLLER_H_
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+
+class ShellAppWindow;
+
+class ShellAppWindowController {
+ public:
+ virtual ~ShellAppWindowController() {}
+
+ // Creates a new app window and adds it to the desktop. This class should
+ // maintain the ownership of the window.
+ virtual ShellAppWindow* CreateAppWindow(content::BrowserContext* context) = 0;
+
+ // Closes and destroys the app windows.
+ virtual void CloseAppWindows() = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_APP_WINDOW_CONTROLLER_H_
diff --git a/extensions/shell/browser/shell_browser_context.cc b/extensions/shell/browser/shell_browser_context.cc
new file mode 100644
index 0000000..2f83782
--- /dev/null
+++ b/extensions/shell/browser/shell_browser_context.cc
@@ -0,0 +1,70 @@
+// 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 "extensions/shell/browser/shell_browser_context.h"
+#include "extensions/shell/browser/shell_special_storage_policy.h"
+
+namespace extensions {
+
+// Create a normal recording browser context. If we used an incognito context
+// then app_shell would also have to create a normal context and manage both.
+ShellBrowserContext::ShellBrowserContext()
+ : content::ShellBrowserContext(false, NULL),
+ storage_policy_(new ShellSpecialStoragePolicy) {
+}
+
+ShellBrowserContext::~ShellBrowserContext() {
+}
+
+quota::SpecialStoragePolicy* ShellBrowserContext::GetSpecialStoragePolicy() {
+ return storage_policy_.get();
+}
+
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext1() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext2() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext3() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext4() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext5() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext6() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext7() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext8() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext9() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext10() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext11() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext12() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext13() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext14() {
+ NOTREACHED();
+}
+void ShellBrowserContext::ProfileFunctionCallOnNonProfileBrowserContext15() {
+ NOTREACHED();
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_browser_context.h b/extensions/shell/browser/shell_browser_context.h
new file mode 100644
index 0000000..72f3fc5
--- /dev/null
+++ b/extensions/shell/browser/shell_browser_context.h
@@ -0,0 +1,53 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_CONTEXT_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_CONTEXT_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "webkit/browser/quota/special_storage_policy.h"
+
+namespace extensions {
+
+class ShellSpecialStoragePolicy;
+
+// The BrowserContext used by the content, apps and extensions systems in
+// app_shell.
+class ShellBrowserContext : public content::ShellBrowserContext {
+ public:
+ ShellBrowserContext();
+ virtual ~ShellBrowserContext();
+
+ // content::BrowserContext implementation.
+ virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() OVERRIDE;
+
+ // HACK: Pad the virtual function table so we trip an assertion if someone
+ // tries to use |this| as a Profile.
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext1();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext2();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext3();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext4();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext5();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext6();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext7();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext8();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext9();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext10();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext11();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext12();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext13();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext14();
+ virtual void ProfileFunctionCallOnNonProfileBrowserContext15();
+
+ private:
+ scoped_refptr<quota::SpecialStoragePolicy> storage_policy_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellBrowserContext);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_CONTEXT_H_
diff --git a/extensions/shell/browser/shell_browser_main_delegate.h b/extensions/shell/browser/shell_browser_main_delegate.h
new file mode 100644
index 0000000..3dbbbab
--- /dev/null
+++ b/extensions/shell/browser/shell_browser_main_delegate.h
@@ -0,0 +1,36 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_MAIN_DELEGATE_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_MAIN_DELEGATE_H_
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+
+class ShellDesktopController;
+
+class ShellBrowserMainDelegate {
+ public:
+ virtual ~ShellBrowserMainDelegate() {}
+
+ // Called to start an application after all initialization processes that are
+ // necesary to run apps are completed.
+ virtual void Start(content::BrowserContext* context) = 0;
+
+ // Called after the main message looop has stopped, but before
+ // other services such as BrowserContext / extension system are shut down.
+ virtual void Shutdown() = 0;
+
+ // Creates the ShellDesktopController instance to initialize the root window
+ // and window manager. Subclass may return its subclass to customize the
+ // windo manager.
+ virtual ShellDesktopController* CreateDesktopController() = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_MAIN_DELEGATE_H_
diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc
new file mode 100644
index 0000000..3a33566
--- /dev/null
+++ b/extensions/shell/browser/shell_browser_main_parts.cc
@@ -0,0 +1,167 @@
+// 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 "extensions/shell/browser/shell_browser_main_parts.h"
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/omaha_query_params/omaha_query_params.h"
+#include "content/public/common/result_codes.h"
+#include "content/shell/browser/shell_devtools_delegate.h"
+#include "content/shell/browser/shell_net_log.h"
+#include "extensions/browser/browser_context_keyed_service_factories.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/shell/browser/shell_browser_context.h"
+#include "extensions/shell/browser/shell_browser_main_delegate.h"
+#include "extensions/shell/browser/shell_desktop_controller.h"
+#include "extensions/shell/browser/shell_extension_system.h"
+#include "extensions/shell/browser/shell_extension_system_factory.h"
+#include "extensions/shell/browser/shell_extensions_browser_client.h"
+#include "extensions/shell/browser/shell_omaha_query_params_delegate.h"
+#include "extensions/shell/common/shell_extensions_client.h"
+#include "extensions/shell/common/switches.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "extensions/shell/browser/shell_network_controller_chromeos.h"
+#endif
+
+using content::BrowserContext;
+
+namespace {
+
+// Register additional KeyedService factories here. See
+// ChromeBrowserMainExtraPartsProfiles for details.
+void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
+ extensions::EnsureBrowserContextKeyedServiceFactoriesBuilt();
+ extensions::ShellExtensionSystemFactory::GetInstance();
+}
+
+} // namespace
+
+namespace extensions {
+
+ShellBrowserMainParts::ShellBrowserMainParts(
+ const content::MainFunctionParams& parameters,
+ ShellBrowserMainDelegate* browser_main_delegate)
+ : extension_system_(NULL),
+ parameters_(parameters),
+ run_message_loop_(true),
+ browser_main_delegate_(browser_main_delegate) {
+}
+
+ShellBrowserMainParts::~ShellBrowserMainParts() {
+}
+
+void ShellBrowserMainParts::PreMainMessageLoopStart() {
+ // TODO(jamescook): Initialize touch here?
+}
+
+void ShellBrowserMainParts::PostMainMessageLoopStart() {
+#if defined(OS_CHROMEOS)
+ chromeos::DBusThreadManager::Initialize();
+ network_controller_.reset(new ShellNetworkController(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
+ switches::kAppShellPreferredNetwork)));
+#else
+ // Non-Chrome OS platforms are for developer convenience, so use a test IME.
+ ui::InitializeInputMethodForTesting();
+#endif
+}
+
+void ShellBrowserMainParts::PreEarlyInitialization() {
+}
+
+int ShellBrowserMainParts::PreCreateThreads() {
+ // TODO(jamescook): Initialize chromeos::CrosSettings here?
+
+ // Return no error.
+ return 0;
+}
+
+void ShellBrowserMainParts::PreMainMessageLoopRun() {
+ // Initialize our "profile" equivalent.
+ browser_context_.reset(new ShellBrowserContext);
+
+ desktop_controller_.reset(browser_main_delegate_->CreateDesktopController());
+ desktop_controller_->CreateRootWindow();
+
+ // NOTE: Much of this is culled from chrome/test/base/chrome_test_suite.cc
+ // TODO(jamescook): Initialize chromeos::UserManager.
+ net_log_.reset(new content::ShellNetLog("app_shell"));
+
+ extensions_client_.reset(new ShellExtensionsClient());
+ ExtensionsClient::Set(extensions_client_.get());
+
+ extensions_browser_client_.reset(
+ new ShellExtensionsBrowserClient(browser_context_.get()));
+ ExtensionsBrowserClient::Set(extensions_browser_client_.get());
+
+ omaha_query_params_delegate_.reset(new ShellOmahaQueryParamsDelegate);
+ omaha_query_params::OmahaQueryParams::SetDelegate(
+ omaha_query_params_delegate_.get());
+
+ // Create our custom ExtensionSystem first because other
+ // KeyedServices depend on it.
+ // TODO(yoz): Move this after EnsureBrowserContextKeyedServiceFactoriesBuilt.
+ CreateExtensionSystem();
+
+ ::EnsureBrowserContextKeyedServiceFactoriesBuilt();
+ BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
+ browser_context_.get());
+
+ devtools_delegate_.reset(
+ new content::ShellDevToolsDelegate(browser_context_.get()));
+ if (parameters_.ui_task) {
+ // For running browser tests.
+ parameters_.ui_task->Run();
+ delete parameters_.ui_task;
+ run_message_loop_ = false;
+ } else {
+ browser_main_delegate_->Start(browser_context_.get());
+ }
+}
+
+bool ShellBrowserMainParts::MainMessageLoopRun(int* result_code) {
+ if (!run_message_loop_)
+ return true;
+ // TODO(yoz): just return false here?
+ base::RunLoop run_loop;
+ run_loop.Run();
+ *result_code = content::RESULT_CODE_NORMAL_EXIT;
+ return true;
+}
+
+void ShellBrowserMainParts::PostMainMessageLoopRun() {
+ browser_main_delegate_->Shutdown();
+
+ BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
+ browser_context_.get());
+ extension_system_ = NULL;
+ ExtensionsBrowserClient::Set(NULL);
+ extensions_browser_client_.reset();
+ browser_context_.reset();
+
+ desktop_controller_.reset();
+}
+
+void ShellBrowserMainParts::PostDestroyThreads() {
+#if defined(OS_CHROMEOS)
+ network_controller_.reset();
+ chromeos::DBusThreadManager::Shutdown();
+#endif
+}
+
+void ShellBrowserMainParts::CreateExtensionSystem() {
+ DCHECK(browser_context_);
+ extension_system_ = static_cast<ShellExtensionSystem*>(
+ ExtensionSystem::Get(browser_context_.get()));
+ extension_system_->InitForRegularProfile(true);
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_browser_main_parts.h b/extensions/shell/browser/shell_browser_main_parts.h
new file mode 100644
index 0000000..83915cb
--- /dev/null
+++ b/extensions/shell/browser/shell_browser_main_parts.h
@@ -0,0 +1,95 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_MAIN_PARTS_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_MAIN_PARTS_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/browser_main_parts.h"
+#include "content/public/common/main_function_params.h"
+#include "ui/aura/window_tree_host_observer.h"
+
+namespace content {
+class ShellDevToolsDelegate;
+struct MainFunctionParams;
+}
+
+namespace views {
+class Widget;
+}
+
+namespace net {
+class NetLog;
+}
+
+namespace extensions {
+
+class ShellBrowserContext;
+class ShellBrowserMainDelegate;
+class ShellDesktopController;
+class ShellExtensionsBrowserClient;
+class ShellExtensionsClient;
+class ShellExtensionSystem;
+class ShellOmahaQueryParamsDelegate;
+
+#if defined(OS_CHROMEOS)
+class ShellNetworkController;
+#endif
+
+// Handles initialization of AppShell.
+class ShellBrowserMainParts : public content::BrowserMainParts {
+ public:
+ ShellBrowserMainParts(const content::MainFunctionParams& parameters,
+ ShellBrowserMainDelegate* browser_main_delegate);
+ virtual ~ShellBrowserMainParts();
+
+ ShellBrowserContext* browser_context() { return browser_context_.get(); }
+
+ ShellExtensionSystem* extension_system() { return extension_system_; }
+
+ // BrowserMainParts overrides.
+ virtual void PreEarlyInitialization() OVERRIDE;
+ virtual void PreMainMessageLoopStart() OVERRIDE;
+ virtual void PostMainMessageLoopStart() OVERRIDE;
+ virtual int PreCreateThreads() OVERRIDE;
+ virtual void PreMainMessageLoopRun() OVERRIDE;
+ virtual bool MainMessageLoopRun(int* result_code) OVERRIDE;
+ virtual void PostMainMessageLoopRun() OVERRIDE;
+ virtual void PostDestroyThreads() OVERRIDE;
+
+ private:
+ // Creates and initializes the ExtensionSystem.
+ void CreateExtensionSystem();
+
+#if defined(OS_CHROMEOS)
+ scoped_ptr<ShellNetworkController> network_controller_;
+#endif
+ scoped_ptr<ShellDesktopController> desktop_controller_;
+ scoped_ptr<ShellBrowserContext> browser_context_;
+ scoped_ptr<ShellExtensionsClient> extensions_client_;
+ scoped_ptr<ShellExtensionsBrowserClient> extensions_browser_client_;
+ scoped_ptr<net::NetLog> net_log_;
+ scoped_ptr<content::ShellDevToolsDelegate> devtools_delegate_;
+ scoped_ptr<ShellOmahaQueryParamsDelegate> omaha_query_params_delegate_;
+
+ // Owned by the KeyedService system.
+ ShellExtensionSystem* extension_system_;
+
+ // For running app browsertests.
+ const content::MainFunctionParams parameters_;
+
+ // If true, indicates the main message loop should be run
+ // in MainMessageLoopRun. If false, it has already been run.
+ bool run_message_loop_;
+
+ scoped_ptr<ShellBrowserMainDelegate> browser_main_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellBrowserMainParts);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_BROWSER_MAIN_PARTS_H_
diff --git a/extensions/shell/browser/shell_browsertest.cc b/extensions/shell/browser/shell_browsertest.cc
new file mode 100644
index 0000000..9520691
--- /dev/null
+++ b/extensions/shell/browser/shell_browsertest.cc
@@ -0,0 +1,31 @@
+// 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 "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/test_utils.h"
+#include "extensions/common/extension_paths.h"
+#include "extensions/shell/test/shell_test.h"
+
+namespace extensions {
+
+// Test that we can open an app window and wait for it to load.
+IN_PROC_BROWSER_TEST_F(AppShellTest, Basic) {
+ base::FilePath test_data_dir;
+
+ content::WindowedNotificationObserver test_pass_observer(
+ chrome::NOTIFICATION_EXTENSION_TEST_PASSED,
+ content::NotificationService::AllSources());
+
+ PathService::Get(extensions::DIR_TEST_DATA, &test_data_dir);
+ test_data_dir = test_data_dir.AppendASCII("platform_app");
+ LoadAndLaunchApp(test_data_dir);
+
+ test_pass_observer.Wait();
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc
new file mode 100644
index 0000000..328fb878
--- /dev/null
+++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -0,0 +1,192 @@
+// 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 "extensions/shell/browser/shell_content_browser_client.h"
+
+#include "base/command_line.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "extensions/browser/extension_message_filter.h"
+#include "extensions/browser/extension_protocols.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/info_map.h"
+#include "extensions/browser/process_map.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/switches.h"
+#include "extensions/shell/browser/shell_browser_context.h"
+#include "extensions/shell/browser/shell_browser_main_parts.h"
+#include "extensions/shell/browser/shell_extension_system.h"
+#include "url/gurl.h"
+
+using content::BrowserThread;
+
+namespace extensions {
+namespace {
+
+ShellContentBrowserClient* g_instance = NULL;
+
+} // namespace
+
+ShellContentBrowserClient::ShellContentBrowserClient(
+ ShellBrowserMainDelegate* browser_main_delegate)
+ : browser_main_parts_(NULL), browser_main_delegate_(browser_main_delegate) {
+ DCHECK(!g_instance);
+ g_instance = this;
+}
+
+ShellContentBrowserClient::~ShellContentBrowserClient() {
+ g_instance = NULL;
+}
+
+// static
+ShellContentBrowserClient* ShellContentBrowserClient::Get() {
+ return g_instance;
+}
+
+content::BrowserContext* ShellContentBrowserClient::GetBrowserContext() {
+ return browser_main_parts_->browser_context();
+}
+
+content::BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts(
+ const content::MainFunctionParams& parameters) {
+ browser_main_parts_ =
+ new ShellBrowserMainParts(parameters, browser_main_delegate_);
+ return browser_main_parts_;
+}
+
+void ShellContentBrowserClient::RenderProcessWillLaunch(
+ content::RenderProcessHost* host) {
+ int render_process_id = host->GetID();
+ host->AddFilter(new ExtensionMessageFilter(
+ render_process_id, browser_main_parts_->browser_context()));
+}
+
+bool ShellContentBrowserClient::ShouldUseProcessPerSite(
+ content::BrowserContext* browser_context,
+ const GURL& effective_url) {
+ // This ensures that all render views created for a single app will use the
+ // same render process (see content::SiteInstance::GetProcess). Otherwise the
+ // default behavior of ContentBrowserClient will lead to separate render
+ // processes for the background page and each app window view.
+ return true;
+}
+
+net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
+ content::BrowserContext* content_browser_context,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) {
+ // Handle only chrome-extension:// requests. app_shell does not support
+ // chrome-extension-resource:// requests (it does not store shared extension
+ // data in its installation directory).
+ InfoMap* extension_info_map =
+ browser_main_parts_->extension_system()->info_map();
+ (*protocol_handlers)[kExtensionScheme] =
+ linked_ptr<net::URLRequestJobFactory::ProtocolHandler>(
+ CreateExtensionProtocolHandler(false /* is_incognito */,
+ extension_info_map));
+ // Let content::ShellBrowserContext handle the rest of the setup.
+ return browser_main_parts_->browser_context()->CreateRequestContext(
+ protocol_handlers, request_interceptors.Pass());
+}
+
+bool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
+ if (!url.is_valid())
+ return false;
+ // Keep in sync with ProtocolHandlers added in CreateRequestContext() and in
+ // content::ShellURLRequestContextGetter::GetURLRequestContext().
+ static const char* const kProtocolList[] = {
+ url::kBlobScheme,
+ content::kChromeDevToolsScheme,
+ content::kChromeUIScheme,
+ url::kDataScheme,
+ url::kFileScheme,
+ url::kFileSystemScheme,
+ kExtensionScheme,
+ kExtensionResourceScheme,
+ };
+ for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
+ if (url.scheme() == kProtocolList[i])
+ return true;
+ }
+ return false;
+}
+
+void ShellContentBrowserClient::SiteInstanceGotProcess(
+ content::SiteInstance* site_instance) {
+ // If this isn't an extension renderer there's nothing to do.
+ const Extension* extension = GetExtension(site_instance);
+ if (!extension)
+ return;
+
+ ProcessMap::Get(browser_main_parts_->browser_context())
+ ->Insert(extension->id(),
+ site_instance->GetProcess()->GetID(),
+ site_instance->GetId());
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&InfoMap::RegisterExtensionProcess,
+ browser_main_parts_->extension_system()->info_map(),
+ extension->id(),
+ site_instance->GetProcess()->GetID(),
+ site_instance->GetId()));
+}
+
+void ShellContentBrowserClient::SiteInstanceDeleting(
+ content::SiteInstance* site_instance) {
+ // If this isn't an extension renderer there's nothing to do.
+ const Extension* extension = GetExtension(site_instance);
+ if (!extension)
+ return;
+
+ ProcessMap::Get(browser_main_parts_->browser_context())
+ ->Remove(extension->id(),
+ site_instance->GetProcess()->GetID(),
+ site_instance->GetId());
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&InfoMap::UnregisterExtensionProcess,
+ browser_main_parts_->extension_system()->info_map(),
+ extension->id(),
+ site_instance->GetProcess()->GetID(),
+ site_instance->GetId()));
+}
+
+void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
+ CommandLine* command_line,
+ int child_process_id) {
+ std::string process_type =
+ command_line->GetSwitchValueASCII(::switches::kProcessType);
+ if (process_type == ::switches::kRendererProcess) {
+ // TODO(jamescook): Should we check here if the process is in the extension
+ // service process map, or can we assume all renderers are extension
+ // renderers?
+ command_line->AppendSwitch(switches::kExtensionProcess);
+ }
+}
+
+void ShellContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
+ std::vector<std::string>* additional_allowed_schemes) {
+ ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
+ additional_allowed_schemes);
+ additional_allowed_schemes->push_back(kExtensionScheme);
+}
+
+const Extension* ShellContentBrowserClient::GetExtension(
+ content::SiteInstance* site_instance) {
+ ExtensionRegistry* registry =
+ ExtensionRegistry::Get(site_instance->GetBrowserContext());
+ return registry->enabled_extensions().GetExtensionOrAppByURL(
+ site_instance->GetSiteURL());
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_content_browser_client.h b/extensions/shell/browser/shell_content_browser_client.h
new file mode 100644
index 0000000..da884fd
--- /dev/null
+++ b/extensions/shell/browser/shell_content_browser_client.h
@@ -0,0 +1,73 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_CONTENT_BROWSER_CLIENT_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_CONTENT_BROWSER_CLIENT_H_
+
+#include "base/compiler_specific.h"
+#include "content/public/browser/content_browser_client.h"
+
+class GURL;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+class Extension;
+class ShellBrowserMainDelegate;
+class ShellBrowserMainParts;
+
+// Content module browser process support for app_shell.
+class ShellContentBrowserClient : public content::ContentBrowserClient {
+ public:
+ explicit ShellContentBrowserClient(
+ ShellBrowserMainDelegate* browser_main_delegate);
+ virtual ~ShellContentBrowserClient();
+
+ // Returns the single instance.
+ static ShellContentBrowserClient* Get();
+
+ // Returns the single browser context for app_shell.
+ content::BrowserContext* GetBrowserContext();
+
+ // content::ContentBrowserClient overrides.
+ virtual content::BrowserMainParts* CreateBrowserMainParts(
+ const content::MainFunctionParams& parameters) OVERRIDE;
+ virtual void RenderProcessWillLaunch(
+ content::RenderProcessHost* host) OVERRIDE;
+ virtual bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
+ const GURL& effective_url) OVERRIDE;
+ virtual net::URLRequestContextGetter* CreateRequestContext(
+ content::BrowserContext* browser_context,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) OVERRIDE;
+ // TODO(jamescook): Quota management?
+ // TODO(jamescook): Speech recognition?
+ virtual bool IsHandledURL(const GURL& url) OVERRIDE;
+ virtual void SiteInstanceGotProcess(
+ content::SiteInstance* site_instance) OVERRIDE;
+ virtual void SiteInstanceDeleting(
+ content::SiteInstance* site_instance) OVERRIDE;
+ virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
+ int child_process_id) OVERRIDE;
+ virtual void GetAdditionalAllowedSchemesForFileSystem(
+ std::vector<std::string>* additional_schemes) OVERRIDE;
+
+ private:
+ // Returns the extension or app associated with |site_instance| or NULL.
+ const Extension* GetExtension(content::SiteInstance* site_instance);
+
+ // Owned by content::BrowserMainLoop.
+ ShellBrowserMainParts* browser_main_parts_;
+
+ // Owned by ShellBrowserMainParts.
+ ShellBrowserMainDelegate* browser_main_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellContentBrowserClient);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_CONTENT_BROWSER_CLIENT_H_
diff --git a/extensions/shell/browser/shell_desktop_controller.cc b/extensions/shell/browser/shell_desktop_controller.cc
new file mode 100644
index 0000000..5cec7fe
--- /dev/null
+++ b/extensions/shell/browser/shell_desktop_controller.cc
@@ -0,0 +1,336 @@
+// 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 "extensions/shell/browser/shell_desktop_controller.h"
+
+#include "base/command_line.h"
+#include "content/public/browser/context_factory.h"
+#include "extensions/shell/browser/shell_app_window_controller.h"
+#include "extensions/shell/common/switches.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/default_capture_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/layout_manager.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/image_cursors.h"
+#include "ui/base/ime/input_method_initializer.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/screen.h"
+#include "ui/wm/core/base_focus_rules.h"
+#include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/core/cursor_manager.h"
+#include "ui/wm/core/focus_controller.h"
+#include "ui/wm/core/input_method_event_filter.h"
+#include "ui/wm/core/native_cursor_manager.h"
+#include "ui/wm/core/native_cursor_manager_delegate.h"
+#include "ui/wm/core/user_activity_detector.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/chromeos/user_activity_power_manager_notifier.h"
+#include "ui/display/types/chromeos/display_mode.h"
+#include "ui/display/types/chromeos/display_snapshot.h"
+#endif
+
+namespace extensions {
+namespace {
+
+// A simple layout manager that makes each new window fill its parent.
+class FillLayout : public aura::LayoutManager {
+ public:
+ FillLayout() {}
+ virtual ~FillLayout() {}
+
+ private:
+ // aura::LayoutManager:
+ virtual void OnWindowResized() OVERRIDE {}
+
+ virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
+ if (!child->parent())
+ return;
+
+ // Create a rect at 0,0 with the size of the parent.
+ gfx::Size parent_size = child->parent()->bounds().size();
+ child->SetBounds(gfx::Rect(parent_size));
+ }
+
+ virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
+
+ virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
+
+ virtual void OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) OVERRIDE {}
+
+ virtual void SetChildBounds(aura::Window* child,
+ const gfx::Rect& requested_bounds) OVERRIDE {
+ SetChildBoundsDirect(child, requested_bounds);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(FillLayout);
+};
+
+// A class that bridges the gap between CursorManager and Aura. It borrows
+// heavily from AshNativeCursorManager.
+class ShellNativeCursorManager : public wm::NativeCursorManager {
+ public:
+ explicit ShellNativeCursorManager(aura::WindowTreeHost* host)
+ : host_(host), image_cursors_(new ui::ImageCursors) {}
+ virtual ~ShellNativeCursorManager() {}
+
+ // wm::NativeCursorManager overrides.
+ virtual void SetDisplay(const gfx::Display& display,
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
+ if (image_cursors_->SetDisplay(display, display.device_scale_factor()))
+ SetCursor(delegate->GetCursor(), delegate);
+ }
+
+ virtual void SetCursor(gfx::NativeCursor cursor,
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
+ image_cursors_->SetPlatformCursor(&cursor);
+ cursor.set_device_scale_factor(image_cursors_->GetScale());
+ delegate->CommitCursor(cursor);
+
+ if (delegate->IsCursorVisible())
+ ApplyCursor(cursor);
+ }
+
+ virtual void SetVisibility(
+ bool visible,
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
+ delegate->CommitVisibility(visible);
+
+ if (visible) {
+ SetCursor(delegate->GetCursor(), delegate);
+ } else {
+ gfx::NativeCursor invisible_cursor(ui::kCursorNone);
+ image_cursors_->SetPlatformCursor(&invisible_cursor);
+ ApplyCursor(invisible_cursor);
+ }
+ }
+
+ virtual void SetCursorSet(
+ ui::CursorSetType cursor_set,
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
+ image_cursors_->SetCursorSet(cursor_set);
+ delegate->CommitCursorSet(cursor_set);
+ if (delegate->IsCursorVisible())
+ SetCursor(delegate->GetCursor(), delegate);
+ }
+
+ virtual void SetMouseEventsEnabled(
+ bool enabled,
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
+ delegate->CommitMouseEventsEnabled(enabled);
+ SetVisibility(delegate->IsCursorVisible(), delegate);
+ }
+
+ private:
+ // Sets |cursor| as the active cursor within Aura.
+ void ApplyCursor(gfx::NativeCursor cursor) { host_->SetCursor(cursor); }
+
+ aura::WindowTreeHost* host_; // Not owned.
+
+ scoped_ptr<ui::ImageCursors> image_cursors_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellNativeCursorManager);
+};
+
+class AppsFocusRules : public wm::BaseFocusRules {
+ public:
+ AppsFocusRules() {}
+ virtual ~AppsFocusRules() {}
+
+ virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE {
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AppsFocusRules);
+};
+
+ShellDesktopController* g_instance = NULL;
+
+} // namespace
+
+ShellDesktopController::ShellDesktopController() {
+#if defined(OS_CHROMEOS)
+ display_configurator_.reset(new ui::DisplayConfigurator);
+ display_configurator_->Init(false);
+ display_configurator_->ForceInitialConfigure(0);
+ display_configurator_->AddObserver(this);
+#endif
+ aura::Env::CreateInstance(true);
+ aura::Env::GetInstance()->set_context_factory(content::GetContextFactory());
+
+ g_instance = this;
+}
+
+ShellDesktopController::~ShellDesktopController() {
+ app_window_controller_.reset();
+ g_instance = NULL;
+ DestroyRootWindow();
+ aura::Env::DeleteInstance();
+}
+
+// static
+ShellDesktopController* ShellDesktopController::instance() {
+ return g_instance;
+}
+
+void ShellDesktopController::SetAppWindowController(
+ ShellAppWindowController* app_window_controller) {
+ app_window_controller_.reset(app_window_controller);
+}
+
+ShellAppWindow* ShellDesktopController::CreateAppWindow(
+ content::BrowserContext* context) {
+ return app_window_controller_->CreateAppWindow(context);
+}
+
+void ShellDesktopController::CloseAppWindows() {
+ if (app_window_controller_)
+ app_window_controller_->CloseAppWindows();
+}
+
+aura::Window* ShellDesktopController::GetDefaultParent(
+ aura::Window* context,
+ aura::Window* window,
+ const gfx::Rect& bounds) {
+ return host_->window();
+}
+
+#if defined(OS_CHROMEOS)
+void ShellDesktopController::OnDisplayModeChanged(
+ const std::vector<ui::DisplayConfigurator::DisplayState>& displays) {
+ gfx::Size size = GetPrimaryDisplaySize();
+ if (!size.IsEmpty())
+ host_->UpdateRootWindowSize(size);
+}
+#endif
+
+void ShellDesktopController::OnHostCloseRequested(
+ const aura::WindowTreeHost* host) {
+ DCHECK_EQ(host_.get(), host);
+ CloseAppWindows();
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::MessageLoop::QuitClosure());
+}
+
+void ShellDesktopController::CreateRootWindow() {
+ // Set up basic pieces of ui::wm.
+ gfx::Size size;
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kAppShellHostWindowBounds)) {
+ const std::string size_str =
+ command_line->GetSwitchValueASCII(switches::kAppShellHostWindowBounds);
+ int width, height;
+ CHECK_EQ(2, sscanf(size_str.c_str(), "%dx%d", &width, &height));
+ size = gfx::Size(width, height);
+ } else {
+ size = GetPrimaryDisplaySize();
+ }
+ if (size.IsEmpty())
+ size = gfx::Size(1280, 720);
+
+ test_screen_.reset(aura::TestScreen::Create(size));
+ // TODO(jamescook): Replace this with a real Screen implementation.
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
+ // TODO(mukai): Set up input method.
+
+ host_.reset(test_screen_->CreateHostForPrimaryDisplay());
+ host_->InitHost();
+ aura::client::SetWindowTreeClient(host_->window(), this);
+ root_window_event_filter_.reset(new wm::CompoundEventFilter);
+ host_->window()->AddPreTargetHandler(root_window_event_filter_.get());
+ InitWindowManager();
+
+ host_->AddObserver(this);
+
+ // Ensure the X window gets mapped.
+ host_->Show();
+}
+
+void ShellDesktopController::InitWindowManager() {
+ wm::FocusController* focus_controller =
+ new wm::FocusController(CreateFocusRules());
+ aura::client::SetFocusClient(host_->window(), focus_controller);
+ host_->window()->AddPreTargetHandler(focus_controller);
+ aura::client::SetActivationClient(host_->window(), focus_controller);
+ focus_client_.reset(focus_controller);
+
+ input_method_filter_.reset(
+ new wm::InputMethodEventFilter(host_->GetAcceleratedWidget()));
+ input_method_filter_->SetInputMethodPropertyInRootWindow(host_->window());
+ root_window_event_filter_->AddHandler(input_method_filter_.get());
+
+ capture_client_.reset(
+ new aura::client::DefaultCaptureClient(host_->window()));
+
+ // Ensure new windows fill the display.
+ host_->window()->SetLayoutManager(new FillLayout);
+
+ cursor_manager_.reset(
+ new wm::CursorManager(scoped_ptr<wm::NativeCursorManager>(
+ new ShellNativeCursorManager(host_.get()))));
+ cursor_manager_->SetDisplay(
+ gfx::Screen::GetNativeScreen()->GetPrimaryDisplay());
+ cursor_manager_->SetCursor(ui::kCursorPointer);
+ aura::client::SetCursorClient(host_->window(), cursor_manager_.get());
+
+ user_activity_detector_.reset(new wm::UserActivityDetector);
+ host_->event_processor()->GetRootTarget()->AddPreTargetHandler(
+ user_activity_detector_.get());
+#if defined(OS_CHROMEOS)
+ user_activity_notifier_.reset(
+ new ui::UserActivityPowerManagerNotifier(user_activity_detector_.get()));
+#endif
+}
+
+wm::FocusRules* ShellDesktopController::CreateFocusRules() {
+ return new AppsFocusRules();
+}
+
+void ShellDesktopController::DestroyRootWindow() {
+ host_->RemoveObserver(this);
+ if (input_method_filter_)
+ root_window_event_filter_->RemoveHandler(input_method_filter_.get());
+ if (user_activity_detector_) {
+ host_->event_processor()->GetRootTarget()->RemovePreTargetHandler(
+ user_activity_detector_.get());
+ }
+ wm::FocusController* focus_controller =
+ static_cast<wm::FocusController*>(focus_client_.get());
+ if (focus_controller) {
+ host_->window()->RemovePreTargetHandler(focus_controller);
+ aura::client::SetActivationClient(host_->window(), NULL);
+ }
+ root_window_event_filter_.reset();
+ capture_client_.reset();
+ input_method_filter_.reset();
+ focus_client_.reset();
+ cursor_manager_.reset();
+#if defined(OS_CHROMEOS)
+ user_activity_notifier_.reset();
+#endif
+ user_activity_detector_.reset();
+ host_.reset();
+}
+
+gfx::Size ShellDesktopController::GetPrimaryDisplaySize() {
+#if defined(OS_CHROMEOS)
+ const std::vector<ui::DisplayConfigurator::DisplayState>& displays =
+ display_configurator_->cached_displays();
+ if (displays.empty())
+ return gfx::Size();
+ const ui::DisplayMode* mode = displays[0].display->current_mode();
+ return mode ? mode->size() : gfx::Size();
+#else
+ return gfx::Size();
+#endif
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_desktop_controller.h b/extensions/shell/browser/shell_desktop_controller.h
new file mode 100644
index 0000000..afaef8a
--- /dev/null
+++ b/extensions/shell/browser/shell_desktop_controller.h
@@ -0,0 +1,149 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/window_tree_host_observer.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/display/chromeos/display_configurator.h"
+#endif
+
+namespace aura {
+class TestScreen;
+class Window;
+class WindowTreeHost;
+namespace client {
+class DefaultCaptureClient;
+class FocusClient;
+}
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace gfx {
+class Size;
+}
+
+#if defined(OS_CHROMEOS)
+namespace ui {
+class UserActivityPowerManagerNotifier;
+}
+#endif
+
+namespace wm {
+class CompoundEventFilter;
+class CursorManager;
+class FocusRules;
+class InputMethodEventFilter;
+class UserActivityDetector;
+}
+
+namespace extensions {
+
+class ShellAppWindow;
+class ShellAppWindowController;
+
+// Handles desktop-related tasks for app_shell.
+class ShellDesktopController : public aura::client::WindowTreeClient,
+ public aura::WindowTreeHostObserver
+#if defined(OS_CHROMEOS)
+ ,
+ public ui::DisplayConfigurator::Observer
+#endif
+ {
+ public:
+ ShellDesktopController();
+ virtual ~ShellDesktopController();
+
+ // Returns the single instance of the desktop. (Stateless functions like
+ // ShellAppWindowCreateFunction need to be able to access the desktop, so
+ // we need a singleton somewhere).
+ static ShellDesktopController* instance();
+
+ aura::WindowTreeHost* host() { return host_.get(); }
+
+ // Creates the window that hosts the app.
+ void CreateRootWindow();
+
+ // Sets the controller to create/close the app windows. Takes the ownership of
+ // |app_window_controller|.
+ void SetAppWindowController(ShellAppWindowController* app_window_controller);
+
+ // Creates a new app window and adds it to the desktop. The desktop maintains
+ // ownership of the window.
+ ShellAppWindow* CreateAppWindow(content::BrowserContext* context);
+
+ // Closes and destroys the app windows.
+ void CloseAppWindows();
+
+ // Overridden from aura::client::WindowTreeClient:
+ virtual aura::Window* GetDefaultParent(aura::Window* context,
+ aura::Window* window,
+ const gfx::Rect& bounds) OVERRIDE;
+
+#if defined(OS_CHROMEOS)
+ // ui::DisplayConfigurator::Observer overrides.
+ virtual void OnDisplayModeChanged(const std::vector<
+ ui::DisplayConfigurator::DisplayState>& displays) OVERRIDE;
+#endif
+
+ // aura::WindowTreeHostObserver overrides:
+ virtual void OnHostCloseRequested(const aura::WindowTreeHost* host) OVERRIDE;
+
+ protected:
+ // Creates and sets the aura clients and window manager stuff. Subclass may
+ // initialize different sets of the clients.
+ virtual void InitWindowManager();
+
+ // Creates a focus rule that is to be used in the InitWindowManager.
+ virtual wm::FocusRules* CreateFocusRules();
+
+ private:
+ // Closes and destroys the root window hosting the app.
+ void DestroyRootWindow();
+
+ // Returns the dimensions (in pixels) of the primary display, or an empty size
+ // if the dimensions can't be determined or no display is connected.
+ gfx::Size GetPrimaryDisplaySize();
+
+#if defined(OS_CHROMEOS)
+ scoped_ptr<ui::DisplayConfigurator> display_configurator_;
+#endif
+
+ scoped_ptr<aura::TestScreen> test_screen_;
+
+ scoped_ptr<aura::WindowTreeHost> host_;
+
+ scoped_ptr<wm::CompoundEventFilter> root_window_event_filter_;
+
+ scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
+
+ scoped_ptr<wm::InputMethodEventFilter> input_method_filter_;
+
+ scoped_ptr<aura::client::FocusClient> focus_client_;
+
+ scoped_ptr<wm::CursorManager> cursor_manager_;
+
+ scoped_ptr<wm::UserActivityDetector> user_activity_detector_;
+#if defined(OS_CHROMEOS)
+ scoped_ptr<ui::UserActivityPowerManagerNotifier> user_activity_notifier_;
+#endif
+
+ // The desktop supports a single app window.
+ scoped_ptr<ShellAppWindowController> app_window_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellDesktopController);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_H_
diff --git a/extensions/shell/browser/shell_extension_system.cc b/extensions/shell/browser/shell_extension_system.cc
new file mode 100644
index 0000000..db14d32
--- /dev/null
+++ b/extensions/shell/browser/shell_extension_system.cc
@@ -0,0 +1,196 @@
+// 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 "extensions/shell/browser/shell_extension_system.h"
+
+#include <string>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "extensions/browser/api/app_runtime/app_runtime_api.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/info_map.h"
+#include "extensions/browser/lazy_background_task_queue.h"
+#include "extensions/browser/process_manager.h"
+#include "extensions/browser/quota_service.h"
+#include "extensions/browser/runtime_data.h"
+#include "extensions/common/file_util.h"
+#include "extensions/shell/browser/api/shell/shell_api.h"
+
+using content::BrowserContext;
+using content::BrowserThread;
+
+namespace extensions {
+
+ShellExtensionSystem::ShellExtensionSystem(BrowserContext* browser_context)
+ : browser_context_(browser_context) {
+}
+
+ShellExtensionSystem::~ShellExtensionSystem() {
+}
+
+bool ShellExtensionSystem::LoadApp(const base::FilePath& app_dir) {
+ // app_shell only supports unpacked extensions.
+ // NOTE: If you add packed extension support consider removing the flag
+ // FOLLOW_SYMLINKS_ANYWHERE below. Packed extensions should not have symlinks.
+ CHECK(base::DirectoryExists(app_dir)) << app_dir.AsUTF8Unsafe();
+ int load_flags = Extension::FOLLOW_SYMLINKS_ANYWHERE;
+ std::string load_error;
+ extension_ = file_util::LoadExtension(
+ app_dir, Manifest::COMMAND_LINE, load_flags, &load_error);
+ if (!extension_) {
+ LOG(ERROR) << "Loading extension at " << app_dir.value()
+ << " 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.
+ // * Call PermissionsUpdater::GrantActivePermissions().
+ // * Call ExtensionService::SatisfyImports().
+ // * Call ExtensionPrefs::OnExtensionInstalled().
+ // * Send NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED.
+
+ ExtensionRegistry::Get(browser_context_)->AddEnabled(extension_);
+
+ RegisterExtensionWithRequestContexts(extension_);
+
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
+ content::Source<BrowserContext>(browser_context_),
+ content::Details<const Extension>(extension_));
+
+ // Inform the rest of the extensions system to start.
+ ready_.Signal();
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_EXTENSIONS_READY,
+ content::Source<BrowserContext>(browser_context_),
+ content::NotificationService::NoDetails());
+ return true;
+}
+
+void ShellExtensionSystem::LaunchApp() {
+ // Send the onLaunched event.
+ DCHECK(extension_.get());
+ AppRuntimeEventRouter::DispatchOnLaunchedEvent(browser_context_,
+ extension_.get());
+}
+
+void ShellExtensionSystem::Shutdown() {
+}
+
+void ShellExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
+ runtime_data_.reset(
+ new RuntimeData(ExtensionRegistry::Get(browser_context_)));
+ lazy_background_task_queue_.reset(
+ new LazyBackgroundTaskQueue(browser_context_));
+ event_router_.reset(
+ new EventRouter(browser_context_, ExtensionPrefs::Get(browser_context_)));
+ process_manager_.reset(ProcessManager::Create(browser_context_));
+ quota_service_.reset(new QuotaService);
+}
+
+ExtensionService* ShellExtensionSystem::extension_service() {
+ return NULL;
+}
+
+RuntimeData* ShellExtensionSystem::runtime_data() {
+ return runtime_data_.get();
+}
+
+ManagementPolicy* ShellExtensionSystem::management_policy() {
+ return NULL;
+}
+
+UserScriptMaster* ShellExtensionSystem::user_script_master() {
+ return NULL;
+}
+
+ProcessManager* ShellExtensionSystem::process_manager() {
+ return process_manager_.get();
+}
+
+StateStore* ShellExtensionSystem::state_store() {
+ return NULL;
+}
+
+StateStore* ShellExtensionSystem::rules_store() {
+ return NULL;
+}
+
+InfoMap* ShellExtensionSystem::info_map() {
+ if (!info_map_.get())
+ info_map_ = new InfoMap;
+ return info_map_;
+}
+
+LazyBackgroundTaskQueue* ShellExtensionSystem::lazy_background_task_queue() {
+ return lazy_background_task_queue_.get();
+}
+
+EventRouter* ShellExtensionSystem::event_router() {
+ return event_router_.get();
+}
+
+ExtensionWarningService* ShellExtensionSystem::warning_service() {
+ return NULL;
+}
+
+Blacklist* ShellExtensionSystem::blacklist() {
+ return NULL;
+}
+
+ErrorConsole* ShellExtensionSystem::error_console() {
+ return NULL;
+}
+
+InstallVerifier* ShellExtensionSystem::install_verifier() {
+ return NULL;
+}
+
+QuotaService* ShellExtensionSystem::quota_service() {
+ return quota_service_.get();
+}
+
+void ShellExtensionSystem::RegisterExtensionWithRequestContexts(
+ const Extension* extension) {
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&InfoMap::AddExtension,
+ info_map(),
+ make_scoped_refptr(extension),
+ base::Time::Now(),
+ false,
+ false));
+}
+
+void ShellExtensionSystem::UnregisterExtensionWithRequestContexts(
+ const std::string& extension_id,
+ const UnloadedExtensionInfo::Reason reason) {
+}
+
+const OneShotEvent& ShellExtensionSystem::ready() const {
+ return ready_;
+}
+
+ContentVerifier* ShellExtensionSystem::content_verifier() {
+ return NULL;
+}
+
+scoped_ptr<ExtensionSet> ShellExtensionSystem::GetDependentExtensions(
+ const Extension* extension) {
+ scoped_ptr<ExtensionSet> empty(new ExtensionSet());
+ return empty.PassAs<ExtensionSet>();
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_extension_system.h b/extensions/shell/browser/shell_extension_system.h
new file mode 100644
index 0000000..b47c9a5
--- /dev/null
+++ b/extensions/shell/browser/shell_extension_system.h
@@ -0,0 +1,102 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_SYSTEM_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_SYSTEM_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/common/one_shot_event.h"
+
+class BrowserContextKeyedServiceFactory;
+
+namespace base {
+class FilePath;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+
+class EventRouter;
+class InfoMap;
+class LazyBackgroundTaskQueue;
+class ProcessManager;
+class RendererStartupHelper;
+
+// A simplified version of ExtensionSystem for app_shell. Allows
+// app_shell to skip initialization of services it doesn't need.
+class ShellExtensionSystem : public ExtensionSystem {
+ public:
+ explicit ShellExtensionSystem(content::BrowserContext* browser_context);
+ virtual ~ShellExtensionSystem();
+
+ // Loads an unpacked application from a directory. Returns true on success.
+ bool LoadApp(const base::FilePath& app_dir);
+
+ // Launch the currently loaded app.
+ void LaunchApp();
+
+ // KeyedService implementation:
+ virtual void Shutdown() OVERRIDE;
+
+ scoped_refptr<Extension> extension() { return extension_; }
+
+ // ExtensionSystem implementation:
+ virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE;
+ virtual ExtensionService* extension_service() OVERRIDE;
+ virtual RuntimeData* runtime_data() OVERRIDE;
+ virtual ManagementPolicy* management_policy() OVERRIDE;
+ virtual UserScriptMaster* user_script_master() OVERRIDE;
+ virtual ProcessManager* process_manager() OVERRIDE;
+ virtual StateStore* state_store() OVERRIDE;
+ virtual StateStore* rules_store() OVERRIDE;
+ virtual InfoMap* info_map() OVERRIDE;
+ virtual LazyBackgroundTaskQueue* lazy_background_task_queue() OVERRIDE;
+ virtual EventRouter* event_router() OVERRIDE;
+ virtual ExtensionWarningService* warning_service() OVERRIDE;
+ virtual Blacklist* blacklist() OVERRIDE;
+ virtual ErrorConsole* error_console() OVERRIDE;
+ virtual InstallVerifier* install_verifier() OVERRIDE;
+ virtual QuotaService* quota_service() OVERRIDE;
+ virtual void RegisterExtensionWithRequestContexts(
+ const Extension* extension) OVERRIDE;
+ virtual void UnregisterExtensionWithRequestContexts(
+ const std::string& extension_id,
+ const UnloadedExtensionInfo::Reason reason) OVERRIDE;
+ virtual const OneShotEvent& ready() const OVERRIDE;
+ virtual ContentVerifier* content_verifier() OVERRIDE;
+ virtual scoped_ptr<ExtensionSet> GetDependentExtensions(
+ const Extension* extension) OVERRIDE;
+
+ private:
+ content::BrowserContext* browser_context_; // Not owned.
+
+ // Extension ID for the app.
+ std::string app_id_;
+
+ scoped_refptr<Extension> extension_;
+
+ // Data to be accessed on the IO thread. Must outlive process_manager_.
+ scoped_refptr<InfoMap> info_map_;
+
+ scoped_ptr<RuntimeData> runtime_data_;
+ scoped_ptr<LazyBackgroundTaskQueue> lazy_background_task_queue_;
+ scoped_ptr<EventRouter> event_router_;
+ scoped_ptr<ProcessManager> process_manager_;
+ scoped_ptr<QuotaService> quota_service_;
+
+ // Signaled when the extension system has completed its startup tasks.
+ OneShotEvent ready_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellExtensionSystem);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_SYSTEM_H_
diff --git a/extensions/shell/browser/shell_extension_system_factory.cc b/extensions/shell/browser/shell_extension_system_factory.cc
new file mode 100644
index 0000000..73ad7d0
--- /dev/null
+++ b/extensions/shell/browser/shell_extension_system_factory.cc
@@ -0,0 +1,52 @@
+// 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 "extensions/shell/browser/shell_extension_system_factory.h"
+
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "extensions/browser/extension_prefs_factory.h"
+#include "extensions/browser/extension_registry_factory.h"
+#include "extensions/shell/browser/shell_extension_system.h"
+
+using content::BrowserContext;
+
+namespace extensions {
+
+ExtensionSystem* ShellExtensionSystemFactory::GetForBrowserContext(
+ BrowserContext* context) {
+ return static_cast<ShellExtensionSystem*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+ShellExtensionSystemFactory* ShellExtensionSystemFactory::GetInstance() {
+ return Singleton<ShellExtensionSystemFactory>::get();
+}
+
+ShellExtensionSystemFactory::ShellExtensionSystemFactory()
+ : ExtensionSystemProvider("ShellExtensionSystem",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(ExtensionPrefsFactory::GetInstance());
+ DependsOn(ExtensionRegistryFactory::GetInstance());
+}
+
+ShellExtensionSystemFactory::~ShellExtensionSystemFactory() {
+}
+
+KeyedService* ShellExtensionSystemFactory::BuildServiceInstanceFor(
+ BrowserContext* context) const {
+ return new ShellExtensionSystem(context);
+}
+
+BrowserContext* ShellExtensionSystemFactory::GetBrowserContextToUse(
+ BrowserContext* context) const {
+ // Use a separate instance for incognito.
+ return context;
+}
+
+bool ShellExtensionSystemFactory::ServiceIsCreatedWithBrowserContext() const {
+ return true;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_extension_system_factory.h b/extensions/shell/browser/shell_extension_system_factory.h
new file mode 100644
index 0000000..5d0a883
--- /dev/null
+++ b/extensions/shell/browser/shell_extension_system_factory.h
@@ -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.
+
+#ifndef EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_SYSTEM_FACTORY_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_SYSTEM_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "extensions/browser/extension_system_provider.h"
+
+namespace extensions {
+
+// A factory that provides ShellExtensionSystem for app_shell.
+class ShellExtensionSystemFactory : public ExtensionSystemProvider {
+ public:
+ // ExtensionSystemProvider implementation:
+ virtual ExtensionSystem* GetForBrowserContext(
+ content::BrowserContext* context) OVERRIDE;
+
+ static ShellExtensionSystemFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<ShellExtensionSystemFactory>;
+
+ ShellExtensionSystemFactory();
+ virtual ~ShellExtensionSystemFactory();
+
+ // BrowserContextKeyedServiceFactory implementation:
+ virtual KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const OVERRIDE;
+ virtual content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const OVERRIDE;
+ virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellExtensionSystemFactory);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_SYSTEM_FACTORY_H_
diff --git a/extensions/shell/browser/shell_extension_web_contents_observer.cc b/extensions/shell/browser/shell_extension_web_contents_observer.cc
new file mode 100644
index 0000000..9dc3691
--- /dev/null
+++ b/extensions/shell/browser/shell_extension_web_contents_observer.cc
@@ -0,0 +1,20 @@
+// 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 "extensions/shell/browser/shell_extension_web_contents_observer.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+ extensions::ShellExtensionWebContentsObserver);
+
+namespace extensions {
+
+ShellExtensionWebContentsObserver::ShellExtensionWebContentsObserver(
+ content::WebContents* web_contents)
+ : ExtensionWebContentsObserver(web_contents) {
+}
+
+ShellExtensionWebContentsObserver::~ShellExtensionWebContentsObserver() {
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_extension_web_contents_observer.h b/extensions/shell/browser/shell_extension_web_contents_observer.h
new file mode 100644
index 0000000..7cec042
--- /dev/null
+++ b/extensions/shell/browser/shell_extension_web_contents_observer.h
@@ -0,0 +1,29 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_WEB_CONTENTS_OBSERVER_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_WEB_CONTENTS_OBSERVER_H_
+
+#include "content/public/browser/web_contents_user_data.h"
+#include "extensions/browser/extension_web_contents_observer.h"
+
+namespace extensions {
+
+// The app_shell version of ExtensionWebContentsObserver.
+class ShellExtensionWebContentsObserver
+ : public ExtensionWebContentsObserver,
+ public content::WebContentsUserData<ShellExtensionWebContentsObserver> {
+ private:
+ friend class content::WebContentsUserData<ShellExtensionWebContentsObserver>;
+
+ explicit ShellExtensionWebContentsObserver(
+ content::WebContents* web_contents);
+ virtual ~ShellExtensionWebContentsObserver();
+
+ DISALLOW_COPY_AND_ASSIGN(ShellExtensionWebContentsObserver);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSION_WEB_CONTENTS_OBSERVER_H_
diff --git a/extensions/shell/browser/shell_extensions_browser_client.cc b/extensions/shell/browser/shell_extensions_browser_client.cc
new file mode 100644
index 0000000..c725ebd
--- /dev/null
+++ b/extensions/shell/browser/shell_extensions_browser_client.cc
@@ -0,0 +1,242 @@
+// 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 "extensions/shell/browser/shell_extensions_browser_client.h"
+
+#include "base/prefs/pref_service.h"
+#include "base/prefs/pref_service_factory.h"
+#include "base/prefs/testing_pref_store.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/user_prefs/user_prefs.h"
+#include "extensions/browser/api/extensions_api_client.h"
+#include "extensions/browser/app_sorting.h"
+#include "extensions/browser/extension_function_registry.h"
+#include "extensions/browser/extension_host_delegate.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/common/api/generated_api.h"
+#include "extensions/shell/browser/shell_app_sorting.h"
+#include "extensions/shell/browser/shell_extension_system_factory.h"
+#include "extensions/shell/browser/shell_extension_web_contents_observer.h"
+#include "extensions/shell/browser/shell_runtime_api_delegate.h"
+#include "extensions/shell/common/api/generated_api.h"
+
+using content::BrowserContext;
+
+namespace extensions {
+namespace {
+
+// See chrome::RegisterProfilePrefs() in chrome/browser/prefs/browser_prefs.cc
+void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) {
+ ExtensionPrefs::RegisterProfilePrefs(registry);
+}
+
+// A minimal ExtensionHostDelegate.
+class ShellExtensionHostDelegate : public ExtensionHostDelegate {
+ public:
+ ShellExtensionHostDelegate() {}
+ virtual ~ShellExtensionHostDelegate() {}
+
+ // ExtensionHostDelegate implementation.
+ virtual void OnExtensionHostCreated(
+ content::WebContents* web_contents) OVERRIDE;
+
+ virtual void OnRenderViewCreatedForBackgroundPage(
+ ExtensionHost* host) OVERRIDE {}
+
+ virtual content::JavaScriptDialogManager* GetJavaScriptDialogManager()
+ OVERRIDE {
+ // TODO(jamescook): Create a JavaScriptDialogManager or reuse the one from
+ // content_shell.
+ NOTREACHED();
+ return NULL;
+ }
+
+ virtual void CreateTab(content::WebContents* web_contents,
+ const std::string& extension_id,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) OVERRIDE {
+ // TODO(jamescook): Should app_shell support opening popup windows?
+ NOTREACHED();
+ }
+
+ virtual void ProcessMediaAccessRequest(
+ content::WebContents* web_contents,
+ const content::MediaStreamRequest& request,
+ const content::MediaResponseCallback& callback,
+ const Extension* extension) OVERRIDE {
+ // app_shell does not support media capture.
+ NOTREACHED();
+ }
+};
+
+void ShellExtensionHostDelegate::OnExtensionHostCreated(
+ content::WebContents* web_contents) {
+ ShellExtensionWebContentsObserver::CreateForWebContents(web_contents);
+}
+
+} // namespace
+
+ShellExtensionsBrowserClient::ShellExtensionsBrowserClient(
+ BrowserContext* context)
+ : browser_context_(context), api_client_(new ExtensionsAPIClient) {
+ // Set up the preferences service.
+ base::PrefServiceFactory factory;
+ factory.set_user_prefs(new TestingPrefStore);
+ factory.set_extension_prefs(new TestingPrefStore);
+ // app_shell should not require syncable preferences, but for now we need to
+ // recycle some of the RegisterProfilePrefs() code in Chrome.
+ // TODO(jamescook): Convert this to PrefRegistrySimple.
+ user_prefs::PrefRegistrySyncable* pref_registry =
+ new user_prefs::PrefRegistrySyncable;
+ // Prefs should be registered before the PrefService is created.
+ RegisterPrefs(pref_registry);
+ prefs_ = factory.Create(pref_registry).Pass();
+ user_prefs::UserPrefs::Set(browser_context_, prefs_.get());
+}
+
+ShellExtensionsBrowserClient::~ShellExtensionsBrowserClient() {
+}
+
+bool ShellExtensionsBrowserClient::IsShuttingDown() {
+ return false;
+}
+
+bool ShellExtensionsBrowserClient::AreExtensionsDisabled(
+ const base::CommandLine& command_line,
+ BrowserContext* context) {
+ return false;
+}
+
+bool ShellExtensionsBrowserClient::IsValidContext(BrowserContext* context) {
+ return context == browser_context_;
+}
+
+bool ShellExtensionsBrowserClient::IsSameContext(BrowserContext* first,
+ BrowserContext* second) {
+ return first == second;
+}
+
+bool ShellExtensionsBrowserClient::HasOffTheRecordContext(
+ BrowserContext* context) {
+ return false;
+}
+
+BrowserContext* ShellExtensionsBrowserClient::GetOffTheRecordContext(
+ BrowserContext* context) {
+ // app_shell only supports a single context.
+ return NULL;
+}
+
+BrowserContext* ShellExtensionsBrowserClient::GetOriginalContext(
+ BrowserContext* context) {
+ return context;
+}
+
+bool ShellExtensionsBrowserClient::IsGuestSession(
+ BrowserContext* context) const {
+ return false;
+}
+
+bool ShellExtensionsBrowserClient::IsExtensionIncognitoEnabled(
+ const std::string& extension_id,
+ content::BrowserContext* context) const {
+ return false;
+}
+
+bool ShellExtensionsBrowserClient::CanExtensionCrossIncognito(
+ const Extension* extension,
+ content::BrowserContext* context) const {
+ return false;
+}
+
+bool ShellExtensionsBrowserClient::IsWebViewRequest(
+ net::URLRequest* request) const {
+ return false;
+}
+
+net::URLRequestJob*
+ShellExtensionsBrowserClient::MaybeCreateResourceBundleRequestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const base::FilePath& directory_path,
+ const std::string& content_security_policy,
+ bool send_cors_header) {
+ return NULL;
+}
+
+bool ShellExtensionsBrowserClient::AllowCrossRendererResourceLoad(
+ net::URLRequest* request,
+ bool is_incognito,
+ const Extension* extension,
+ InfoMap* extension_info_map) {
+ // Note: This may need to change if app_shell supports webview.
+ return false;
+}
+
+PrefService* ShellExtensionsBrowserClient::GetPrefServiceForContext(
+ BrowserContext* context) {
+ return prefs_.get();
+}
+
+void ShellExtensionsBrowserClient::GetEarlyExtensionPrefsObservers(
+ content::BrowserContext* context,
+ std::vector<ExtensionPrefsObserver*>* observers) const {
+}
+
+ProcessManagerDelegate*
+ShellExtensionsBrowserClient::GetProcessManagerDelegate() const {
+ return NULL;
+}
+
+scoped_ptr<ExtensionHostDelegate>
+ShellExtensionsBrowserClient::CreateExtensionHostDelegate() {
+ return scoped_ptr<ExtensionHostDelegate>(new ShellExtensionHostDelegate);
+}
+
+bool ShellExtensionsBrowserClient::DidVersionUpdate(BrowserContext* context) {
+ // TODO(jamescook): We might want to tell extensions when app_shell updates.
+ return false;
+}
+
+scoped_ptr<AppSorting> ShellExtensionsBrowserClient::CreateAppSorting() {
+ return scoped_ptr<AppSorting>(new ShellAppSorting);
+}
+
+bool ShellExtensionsBrowserClient::IsRunningInForcedAppMode() {
+ return false;
+}
+
+ApiActivityMonitor* ShellExtensionsBrowserClient::GetApiActivityMonitor(
+ BrowserContext* context) {
+ // app_shell doesn't monitor API function calls or events.
+ return NULL;
+}
+
+ExtensionSystemProvider*
+ShellExtensionsBrowserClient::GetExtensionSystemFactory() {
+ return ShellExtensionSystemFactory::GetInstance();
+}
+
+void ShellExtensionsBrowserClient::RegisterExtensionFunctions(
+ ExtensionFunctionRegistry* registry) const {
+ // Register core extension-system APIs.
+ core_api::GeneratedFunctionRegistry::RegisterAll(registry);
+
+ // Register chrome.shell APIs.
+ shell_api::GeneratedFunctionRegistry::RegisterAll(registry);
+}
+
+scoped_ptr<RuntimeAPIDelegate>
+ShellExtensionsBrowserClient::CreateRuntimeAPIDelegate(
+ content::BrowserContext* context) const {
+ return scoped_ptr<RuntimeAPIDelegate>(new ShellRuntimeAPIDelegate());
+}
+
+ComponentExtensionResourceManager*
+ShellExtensionsBrowserClient::GetComponentExtensionResourceManager() {
+ return NULL;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_extensions_browser_client.h b/extensions/shell/browser/shell_extensions_browser_client.h
new file mode 100644
index 0000000..648c7aa
--- /dev/null
+++ b/extensions/shell/browser/shell_extensions_browser_client.h
@@ -0,0 +1,93 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_CLIENT_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_CLIENT_H_
+
+#include "base/compiler_specific.h"
+#include "extensions/browser/extensions_browser_client.h"
+
+class PrefService;
+
+namespace extensions {
+
+class ExtensionsAPIClient;
+
+// An ExtensionsBrowserClient that supports a single content::BrowserContent
+// with no related incognito context.
+class ShellExtensionsBrowserClient : public ExtensionsBrowserClient {
+ public:
+ // |context| is the single BrowserContext used for IsValidContext() below.
+ explicit ShellExtensionsBrowserClient(content::BrowserContext* context);
+ virtual ~ShellExtensionsBrowserClient();
+
+ // ExtensionsBrowserClient overrides:
+ virtual bool IsShuttingDown() OVERRIDE;
+ virtual bool AreExtensionsDisabled(const base::CommandLine& command_line,
+ content::BrowserContext* context) OVERRIDE;
+ virtual bool IsValidContext(content::BrowserContext* context) OVERRIDE;
+ virtual bool IsSameContext(content::BrowserContext* first,
+ content::BrowserContext* second) OVERRIDE;
+ virtual bool HasOffTheRecordContext(
+ content::BrowserContext* context) OVERRIDE;
+ virtual content::BrowserContext* GetOffTheRecordContext(
+ content::BrowserContext* context) OVERRIDE;
+ virtual content::BrowserContext* GetOriginalContext(
+ content::BrowserContext* context) OVERRIDE;
+ virtual bool IsGuestSession(content::BrowserContext* context) const OVERRIDE;
+ virtual bool IsExtensionIncognitoEnabled(
+ const std::string& extension_id,
+ content::BrowserContext* context) const OVERRIDE;
+ virtual bool CanExtensionCrossIncognito(
+ const Extension* extension,
+ content::BrowserContext* context) const OVERRIDE;
+ virtual bool IsWebViewRequest(net::URLRequest* request) const OVERRIDE;
+ virtual net::URLRequestJob* MaybeCreateResourceBundleRequestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const base::FilePath& directory_path,
+ const std::string& content_security_policy,
+ bool send_cors_header) OVERRIDE;
+ virtual bool AllowCrossRendererResourceLoad(
+ net::URLRequest* request,
+ bool is_incognito,
+ const Extension* extension,
+ InfoMap* extension_info_map) OVERRIDE;
+ virtual PrefService* GetPrefServiceForContext(
+ content::BrowserContext* context) OVERRIDE;
+ virtual void GetEarlyExtensionPrefsObservers(
+ content::BrowserContext* context,
+ std::vector<ExtensionPrefsObserver*>* observers) const OVERRIDE;
+ virtual ProcessManagerDelegate* GetProcessManagerDelegate() const OVERRIDE;
+ virtual scoped_ptr<ExtensionHostDelegate> CreateExtensionHostDelegate()
+ OVERRIDE;
+ virtual bool DidVersionUpdate(content::BrowserContext* context) OVERRIDE;
+ virtual scoped_ptr<AppSorting> CreateAppSorting() OVERRIDE;
+ virtual bool IsRunningInForcedAppMode() OVERRIDE;
+ virtual ApiActivityMonitor* GetApiActivityMonitor(
+ content::BrowserContext* context) OVERRIDE;
+ virtual ExtensionSystemProvider* GetExtensionSystemFactory() OVERRIDE;
+ virtual void RegisterExtensionFunctions(
+ ExtensionFunctionRegistry* registry) const OVERRIDE;
+ virtual scoped_ptr<RuntimeAPIDelegate> CreateRuntimeAPIDelegate(
+ content::BrowserContext* context) const OVERRIDE;
+ virtual ComponentExtensionResourceManager*
+ GetComponentExtensionResourceManager() OVERRIDE;
+
+ private:
+ // The single BrowserContext for app_shell. Not owned.
+ content::BrowserContext* browser_context_;
+
+ // Support for extension APIs.
+ scoped_ptr<ExtensionsAPIClient> api_client_;
+
+ // The PrefService for |browser_context_|.
+ scoped_ptr<PrefService> prefs_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellExtensionsBrowserClient);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_CLIENT_H_
diff --git a/extensions/shell/browser/shell_network_controller_chromeos.cc b/extensions/shell/browser/shell_network_controller_chromeos.cc
new file mode 100644
index 0000000..d321e23
--- /dev/null
+++ b/extensions/shell/browser/shell_network_controller_chromeos.cc
@@ -0,0 +1,210 @@
+// 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 "extensions/shell/browser/shell_network_controller_chromeos.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "chromeos/network/network_connection_handler.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_handler_callbacks.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace extensions {
+
+namespace {
+
+// Frequency at which networks should be scanned when not connected to a network
+// or when connected to a non-preferred network.
+const int kScanIntervalSec = 10;
+
+void HandleEnableWifiError(const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ LOG(WARNING) << "Unable to enable wifi: " << error_name;
+}
+
+// Returns a human-readable name for the network described by |network|.
+std::string GetNetworkName(const chromeos::NetworkState& network) {
+ return !network.name().empty()
+ ? network.name()
+ : base::StringPrintf("[%s]", network.type().c_str());
+}
+
+// Returns true if shill is either connected or connecting to a network.
+bool IsConnectedOrConnecting() {
+ chromeos::NetworkStateHandler* state_handler =
+ chromeos::NetworkHandler::Get()->network_state_handler();
+ return state_handler->ConnectedNetworkByType(
+ chromeos::NetworkTypePattern::Default()) ||
+ state_handler->ConnectingNetworkByType(
+ chromeos::NetworkTypePattern::Default());
+}
+
+} // namespace
+
+ShellNetworkController::ShellNetworkController(
+ const std::string& preferred_network_name)
+ : state_(STATE_IDLE),
+ preferred_network_name_(preferred_network_name),
+ preferred_network_is_active_(false),
+ weak_ptr_factory_(this) {
+ chromeos::NetworkHandler::Initialize();
+ chromeos::NetworkStateHandler* state_handler =
+ chromeos::NetworkHandler::Get()->network_state_handler();
+ state_handler->AddObserver(this, FROM_HERE);
+ state_handler->SetTechnologyEnabled(
+ chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi),
+ true,
+ base::Bind(&HandleEnableWifiError));
+
+ // If we're unconnected, trigger a connection attempt and start scanning.
+ NetworkConnectionStateChanged(NULL);
+}
+
+ShellNetworkController::~ShellNetworkController() {
+ chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+ this, FROM_HERE);
+ chromeos::NetworkHandler::Shutdown();
+}
+
+void ShellNetworkController::NetworkListChanged() {
+ VLOG(1) << "Network list changed";
+ ConnectIfUnconnected();
+}
+
+void ShellNetworkController::NetworkConnectionStateChanged(
+ const chromeos::NetworkState* network) {
+ if (network) {
+ VLOG(1) << "Network connection state changed:"
+ << " name=" << GetNetworkName(*network)
+ << " type=" << network->type() << " path=" << network->path()
+ << " state=" << network->connection_state();
+ } else {
+ VLOG(1) << "Network connection state changed: [none]";
+ }
+
+ const chromeos::NetworkState* wifi_network = GetActiveWiFiNetwork();
+ preferred_network_is_active_ =
+ wifi_network && wifi_network->name() == preferred_network_name_;
+ VLOG(2) << "Active WiFi network is "
+ << (wifi_network ? wifi_network->name() : std::string("[none]"));
+
+ if (preferred_network_is_active_ ||
+ (preferred_network_name_.empty() && wifi_network)) {
+ SetScanningEnabled(false);
+ } else {
+ SetScanningEnabled(true);
+ ConnectIfUnconnected();
+ }
+}
+
+const chromeos::NetworkState* ShellNetworkController::GetActiveWiFiNetwork() {
+ chromeos::NetworkStateHandler* state_handler =
+ chromeos::NetworkHandler::Get()->network_state_handler();
+ const chromeos::NetworkState* network = state_handler->FirstNetworkByType(
+ chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi));
+ return network &&
+ (network->IsConnectedState() || network->IsConnectingState())
+ ? network
+ : NULL;
+}
+
+void ShellNetworkController::SetScanningEnabled(bool enabled) {
+ const bool currently_enabled = scan_timer_.IsRunning();
+ if (enabled == currently_enabled)
+ return;
+
+ VLOG(1) << (enabled ? "Starting" : "Stopping") << " scanning";
+ if (enabled) {
+ RequestScan();
+ scan_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(kScanIntervalSec),
+ this,
+ &ShellNetworkController::RequestScan);
+ } else {
+ scan_timer_.Stop();
+ }
+}
+
+void ShellNetworkController::RequestScan() {
+ VLOG(1) << "Requesting scan";
+ chromeos::NetworkHandler::Get()->network_state_handler()->RequestScan();
+}
+
+void ShellNetworkController::ConnectIfUnconnected() {
+ // Don't do anything if the default network is already the preferred one or if
+ // we have a pending request to connect to it.
+ if (preferred_network_is_active_ ||
+ state_ == STATE_WAITING_FOR_PREFERRED_RESULT)
+ return;
+
+ const chromeos::NetworkState* best_network = NULL;
+ bool can_connect_to_preferred_network = false;
+
+ chromeos::NetworkHandler* handler = chromeos::NetworkHandler::Get();
+ chromeos::NetworkStateHandler::NetworkStateList network_list;
+ handler->network_state_handler()->GetVisibleNetworkListByType(
+ chromeos::NetworkTypePattern::WiFi(), &network_list);
+ for (chromeos::NetworkStateHandler::NetworkStateList::const_iterator it =
+ network_list.begin();
+ it != network_list.end();
+ ++it) {
+ const chromeos::NetworkState* network = *it;
+ if (!network->connectable())
+ continue;
+
+ if (!preferred_network_name_.empty() &&
+ network->name() == preferred_network_name_) {
+ best_network = network;
+ can_connect_to_preferred_network = true;
+ break;
+ } else if (!best_network) {
+ best_network = network;
+ }
+ }
+
+ // Don't switch networks if we're already connecting/connected and wouldn't be
+ // switching to the preferred network.
+ if ((IsConnectedOrConnecting() || state_ != STATE_IDLE) &&
+ !can_connect_to_preferred_network)
+ return;
+
+ if (!best_network) {
+ VLOG(1) << "Didn't find any connectable networks";
+ return;
+ }
+
+ VLOG(1) << "Connecting to network " << GetNetworkName(*best_network)
+ << " with path " << best_network->path() << " and strength "
+ << best_network->signal_strength();
+ state_ = can_connect_to_preferred_network
+ ? STATE_WAITING_FOR_PREFERRED_RESULT
+ : STATE_WAITING_FOR_NON_PREFERRED_RESULT;
+ handler->network_connection_handler()->ConnectToNetwork(
+ best_network->path(),
+ base::Bind(&ShellNetworkController::HandleConnectionSuccess,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&ShellNetworkController::HandleConnectionError,
+ weak_ptr_factory_.GetWeakPtr()),
+ false /* check_error_state */);
+}
+
+void ShellNetworkController::HandleConnectionSuccess() {
+ VLOG(1) << "Successfully connected to network";
+ state_ = STATE_IDLE;
+}
+
+void ShellNetworkController::HandleConnectionError(
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ LOG(WARNING) << "Unable to connect to network: " << error_name;
+ state_ = STATE_IDLE;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_network_controller_chromeos.h b/extensions/shell/browser/shell_network_controller_chromeos.h
new file mode 100644
index 0000000..5299aa0
--- /dev/null
+++ b/extensions/shell/browser/shell_network_controller_chromeos.h
@@ -0,0 +1,86 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_NETWORK_CONTROLLER_CHROMEOS_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_NETWORK_CONTROLLER_CHROMEOS_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "base/values.h"
+#include "chromeos/network/network_state_handler_observer.h"
+
+namespace extensions {
+
+// Handles network-related tasks for app_shell on Chrome OS.
+class ShellNetworkController : public chromeos::NetworkStateHandlerObserver {
+ public:
+ // This class must be instantiated after chromeos::DBusThreadManager and
+ // destroyed before it.
+ explicit ShellNetworkController(const std::string& preferred_network_name);
+ virtual ~ShellNetworkController();
+
+ // chromeos::NetworkStateHandlerObserver overrides:
+ virtual void NetworkListChanged() OVERRIDE;
+ virtual void NetworkConnectionStateChanged(
+ const chromeos::NetworkState* state) OVERRIDE;
+
+ private:
+ // State of communication with the connection manager.
+ enum State {
+ // No in-progress requests.
+ STATE_IDLE = 0,
+ // Waiting for the result of an attempt to connect to the preferred network.
+ STATE_WAITING_FOR_PREFERRED_RESULT,
+ // Waiting for the result of an attempt to connect to a non-preferred
+ // network.
+ STATE_WAITING_FOR_NON_PREFERRED_RESULT,
+ };
+
+ // Returns the connected or connecting WiFi network or NULL if no network
+ // matches that description.
+ const chromeos::NetworkState* GetActiveWiFiNetwork();
+
+ // Controls whether scanning is performed periodically.
+ void SetScanningEnabled(bool enabled);
+
+ // Asks the connection manager to scan for networks.
+ void RequestScan();
+
+ // If not currently connected or connecting, chooses a wireless network and
+ // asks the connection manager to connect to it. Also switches to
+ // |preferred_network_name_| if possible.
+ void ConnectIfUnconnected();
+
+ // Handles a successful or failed connection attempt.
+ void HandleConnectionSuccess();
+ void HandleConnectionError(const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data);
+
+ // Current status of communication with the chromeos::NetworkStateHandler.
+ // This is tracked to avoid sending duplicate requests before the handler has
+ // acknowledged the initial connection attempt.
+ State state_;
+
+ // Invokes RequestScan() periodically.
+ base::RepeatingTimer<ShellNetworkController> scan_timer_;
+
+ // Optionally-supplied name of the preferred network.
+ std::string preferred_network_name_;
+
+ // True if the preferred network is connected or connecting.
+ bool preferred_network_is_active_;
+
+ base::WeakPtrFactory<ShellNetworkController> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellNetworkController);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_NETWORK_CONTROLLER_CHROMEOS_H_
diff --git a/extensions/shell/browser/shell_omaha_query_params_delegate.cc b/extensions/shell/browser/shell_omaha_query_params_delegate.cc
new file mode 100644
index 0000000..cd37c718
--- /dev/null
+++ b/extensions/shell/browser/shell_omaha_query_params_delegate.cc
@@ -0,0 +1,22 @@
+// 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 "extensions/shell/browser/shell_omaha_query_params_delegate.h"
+
+namespace extensions {
+
+ShellOmahaQueryParamsDelegate::ShellOmahaQueryParamsDelegate() {
+}
+
+ShellOmahaQueryParamsDelegate::~ShellOmahaQueryParamsDelegate() {
+}
+
+std::string ShellOmahaQueryParamsDelegate::GetExtraParams() {
+ // This version number is high enough to be supported by Omaha
+ // (below 31 is unsupported), but it's fake enough to be obviously
+ // not a Chrome release.
+ return "&prodversion=38.1234.5678.9";
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_omaha_query_params_delegate.h b/extensions/shell/browser/shell_omaha_query_params_delegate.h
new file mode 100644
index 0000000..7ecb5ba
--- /dev/null
+++ b/extensions/shell/browser/shell_omaha_query_params_delegate.h
@@ -0,0 +1,26 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_OMAHA_QUERY_PARAMS_DELEGATE_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_OMAHA_QUERY_PARAMS_DELEGATE_H_
+
+#include "components/omaha_query_params/omaha_query_params_delegate.h"
+
+namespace extensions {
+
+class ShellOmahaQueryParamsDelegate
+ : public omaha_query_params::OmahaQueryParamsDelegate {
+ public:
+ ShellOmahaQueryParamsDelegate();
+ virtual ~ShellOmahaQueryParamsDelegate();
+
+ virtual std::string GetExtraParams() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellOmahaQueryParamsDelegate);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_OMAHA_QUERY_PARAMS_DELEGATE_H_
diff --git a/extensions/shell/browser/shell_runtime_api_delegate.cc b/extensions/shell/browser/shell_runtime_api_delegate.cc
new file mode 100644
index 0000000..3c63da7
--- /dev/null
+++ b/extensions/shell/browser/shell_runtime_api_delegate.cc
@@ -0,0 +1,66 @@
+// 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 "extensions/shell/browser/shell_runtime_api_delegate.h"
+
+#include "extensions/common/api/runtime.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager_client.h"
+#endif
+
+using extensions::core_api::runtime::PlatformInfo;
+
+namespace extensions {
+
+ShellRuntimeAPIDelegate::ShellRuntimeAPIDelegate() {
+}
+
+ShellRuntimeAPIDelegate::~ShellRuntimeAPIDelegate() {
+}
+
+void ShellRuntimeAPIDelegate::AddUpdateObserver(UpdateObserver* observer) {
+}
+
+void ShellRuntimeAPIDelegate::RemoveUpdateObserver(UpdateObserver* observer) {
+}
+
+base::Version ShellRuntimeAPIDelegate::GetPreviousExtensionVersion(
+ const Extension* extension) {
+ return base::Version();
+}
+
+void ShellRuntimeAPIDelegate::ReloadExtension(const std::string& extension_id) {
+}
+
+bool ShellRuntimeAPIDelegate::CheckForUpdates(
+ const std::string& extension_id,
+ const UpdateCheckCallback& callback) {
+ return false;
+}
+
+void ShellRuntimeAPIDelegate::OpenURL(const GURL& uninstall_url) {
+}
+
+bool ShellRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) {
+#if defined(OS_CHROMEOS)
+ info->os = PlatformInfo::OS_CROS_;
+#elif defined(OS_LINUX)
+ info->os = PlatformInfo::OS_LINUX_;
+#endif
+ return true;
+}
+
+bool ShellRuntimeAPIDelegate::RestartDevice(std::string* error_message) {
+// We allow chrome.runtime.restart() to request a device restart on ChromeOS.
+#if defined(OS_CHROMEOS)
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
+ return true;
+#endif
+ *error_message = "Restart is only supported on ChromeOS.";
+ return false;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_runtime_api_delegate.h b/extensions/shell/browser/shell_runtime_api_delegate.h
new file mode 100644
index 0000000..1382ec5
--- /dev/null
+++ b/extensions/shell/browser/shell_runtime_api_delegate.h
@@ -0,0 +1,36 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_RUNTIME_API_DELEGATE_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_RUNTIME_API_DELEGATE_H_
+
+#include "base/macros.h"
+#include "extensions/browser/api/runtime/runtime_api_delegate.h"
+
+namespace extensions {
+
+class ShellRuntimeAPIDelegate : public RuntimeAPIDelegate {
+ public:
+ ShellRuntimeAPIDelegate();
+ virtual ~ShellRuntimeAPIDelegate();
+
+ // RuntimeAPIDelegate implementation.
+ virtual void AddUpdateObserver(UpdateObserver* observer) OVERRIDE;
+ virtual void RemoveUpdateObserver(UpdateObserver* observer) OVERRIDE;
+ virtual base::Version GetPreviousExtensionVersion(
+ const Extension* extension) OVERRIDE;
+ virtual void ReloadExtension(const std::string& extension_id) OVERRIDE;
+ virtual bool CheckForUpdates(const std::string& extension_id,
+ const UpdateCheckCallback& callback) OVERRIDE;
+ virtual void OpenURL(const GURL& uninstall_url) OVERRIDE;
+ virtual bool GetPlatformInfo(core_api::runtime::PlatformInfo* info) OVERRIDE;
+ virtual bool RestartDevice(std::string* error_message) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellRuntimeAPIDelegate);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_RUNTIME_API_DELEGATE_H_
diff --git a/extensions/shell/browser/shell_special_storage_policy.cc b/extensions/shell/browser/shell_special_storage_policy.cc
new file mode 100644
index 0000000..a5f4120
--- /dev/null
+++ b/extensions/shell/browser/shell_special_storage_policy.cc
@@ -0,0 +1,43 @@
+// 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 "extensions/shell/browser/shell_special_storage_policy.h"
+
+namespace extensions {
+
+ShellSpecialStoragePolicy::ShellSpecialStoragePolicy() {
+}
+
+ShellSpecialStoragePolicy::~ShellSpecialStoragePolicy() {
+}
+
+bool ShellSpecialStoragePolicy::IsStorageProtected(const GURL& origin) {
+ return true;
+}
+
+bool ShellSpecialStoragePolicy::IsStorageUnlimited(const GURL& origin) {
+ return true;
+}
+
+bool ShellSpecialStoragePolicy::IsStorageSessionOnly(const GURL& origin) {
+ return false;
+}
+
+bool ShellSpecialStoragePolicy::CanQueryDiskSize(const GURL& origin) {
+ return true;
+}
+
+bool ShellSpecialStoragePolicy::HasSessionOnlyOrigins() {
+ return false;
+}
+
+bool ShellSpecialStoragePolicy::IsFileHandler(const std::string& extension_id) {
+ return true;
+}
+
+bool ShellSpecialStoragePolicy::HasIsolatedStorage(const GURL& origin) {
+ return false;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/browser/shell_special_storage_policy.h b/extensions/shell/browser/shell_special_storage_policy.h
new file mode 100644
index 0000000..d2725d5
--- /dev/null
+++ b/extensions/shell/browser/shell_special_storage_policy.h
@@ -0,0 +1,33 @@
+// 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 EXTENSIONS_SHELL_BROWSER_SHELL_SPECIAL_STORAGE_POLICY_H_
+#define EXTENSIONS_SHELL_BROWSER_SHELL_SPECIAL_STORAGE_POLICY_H_
+
+#include "webkit/browser/quota/special_storage_policy.h"
+
+namespace extensions {
+
+// A simple storage policy for app_shell which does not limit storage
+// capabilities and aims to be as permissive as possible.
+class ShellSpecialStoragePolicy : public quota::SpecialStoragePolicy {
+ public:
+ ShellSpecialStoragePolicy();
+
+ // quota::SpecialStoragePolicy implementation.
+ virtual bool IsStorageProtected(const GURL& origin) OVERRIDE;
+ virtual bool IsStorageUnlimited(const GURL& origin) OVERRIDE;
+ virtual bool IsStorageSessionOnly(const GURL& origin) OVERRIDE;
+ virtual bool CanQueryDiskSize(const GURL& origin) OVERRIDE;
+ virtual bool IsFileHandler(const std::string& extension_id) OVERRIDE;
+ virtual bool HasIsolatedStorage(const GURL& origin) OVERRIDE;
+ virtual bool HasSessionOnlyOrigins() OVERRIDE;
+
+ protected:
+ virtual ~ShellSpecialStoragePolicy();
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_BROWSER_SHELL_SPECIAL_STORAGE_POLICY_H
diff --git a/extensions/shell/common/api/_api_features.json b/extensions/shell/common/api/_api_features.json
new file mode 100644
index 0000000..bcb5f71
--- /dev/null
+++ b/extensions/shell/common/api/_api_features.json
@@ -0,0 +1,18 @@
+// 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.
+
+// This features file defines extension APIs implemented under src/extensions/shell.
+// See extensions/common/features/* to understand this file, in particular
+// feature.h, simple_feature.h, and base_feature_provider.h.
+//
+// Note that specifying "web_page", "blessed_web_page", or "all" as a context
+// type will require manually updating chrome/renderer/resources/dispatcher.cc.
+
+{
+ "shell": {
+ "channel": "dev",
+ "contexts": ["blessed_extension"],
+ "extension_types": ["platform_app"]
+ }
+}
diff --git a/extensions/shell/common/api/api.gyp b/extensions/shell/common/api/api.gyp
new file mode 100644
index 0000000..2a4d126
--- /dev/null
+++ b/extensions/shell/common/api/api.gyp
@@ -0,0 +1,36 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'shell_api',
+ 'type': 'static_library',
+ 'sources': [
+ '<@(schema_files)',
+ ],
+ # TODO(jschuh): http://crbug.com/167187 size_t -> int
+ 'msvs_disabled_warnings': [ 4267 ],
+ 'includes': [
+ '../../../../build/json_schema_bundle_compile.gypi',
+ '../../../../build/json_schema_compile.gypi',
+ ],
+ 'variables': {
+ 'chromium_code': 1,
+ 'non_compiled_schema_files': [
+ ],
+ # TODO(thestig): Eliminate these on Android. See crbug.com/305852.
+ 'schema_files': [
+ 'shell.idl',
+ ],
+ 'cc_dir': 'extensions/shell/common/api',
+ 'root_namespace': 'extensions::shell_api',
+ 'impl_dir': 'extensions/shell/browser/api',
+ },
+ 'dependencies': [
+ '<(DEPTH)/skia/skia.gyp:skia',
+ ],
+ },
+ ],
+}
diff --git a/extensions/shell/common/api/shell.idl b/extensions/shell/common/api/shell.idl
new file mode 100644
index 0000000..0259535
--- /dev/null
+++ b/extensions/shell/common/api/shell.idl
@@ -0,0 +1,36 @@
+// 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.
+
+// Use the <code>chrome.shell</code> API to create windows. The
+// <code>createWindow</code> API is a subset of
+// <code>chrome.app.window.create</code>.
+namespace shell {
+
+ // Called in the creating window (parent) before the load event is called in
+ // the created window (child). The parent can set fields or functions on the
+ // child usable from onload. E.g. background.js:<br>
+ // <code>function(createdWindow) { createdWindow.contentWindow.foo =
+ // function () { }; };</code>
+ // <br>window.js:<br>
+ // <code>window.onload = function () { foo(); }</code>
+ callback CreateWindowCallback =
+ void ([instanceOf=AppWindow] object createdWindow);
+
+ [noinline_doc] dictionary AppWindow {
+ // The JavaScript 'window' object for the created child.
+ [instanceOf=Window] object contentWindow;
+ };
+
+ interface Functions {
+ // Creates a fullscreen window on the default display. Options are ignored.
+ static void createWindow(DOMString url,
+ optional object optionsPlaceholder,
+ optional CreateWindowCallback callback);
+
+ // Returns an $(ref:AppWindow) object for the current script context
+ // (i.e. JavaScript 'window' object).
+ [nocompile] static AppWindow currentWindow();
+ [nocompile, nodoc] static void initializeAppWindow();
+ };
+};
diff --git a/extensions/shell/common/shell_content_client.cc b/extensions/shell/common/shell_content_client.cc
new file mode 100644
index 0000000..5f0df03
--- /dev/null
+++ b/extensions/shell/common/shell_content_client.cc
@@ -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.
+
+#include "extensions/shell/common/shell_content_client.h"
+
+#include "base/strings/string_piece.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/user_agent.h"
+#include "extensions/common/constants.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace extensions {
+
+ShellContentClient::ShellContentClient() {
+}
+
+ShellContentClient::~ShellContentClient() {
+}
+
+void ShellContentClient::AddAdditionalSchemes(
+ std::vector<std::string>* standard_schemes,
+ std::vector<std::string>* savable_schemes) {
+ standard_schemes->push_back(kExtensionScheme);
+ savable_schemes->push_back(kExtensionScheme);
+ standard_schemes->push_back(kExtensionResourceScheme);
+ savable_schemes->push_back(kExtensionResourceScheme);
+}
+
+std::string ShellContentClient::GetUserAgent() const {
+ // TODO(derat): Figure out what this should be for app_shell and determine
+ // whether we need to include a version number to placate browser sniffing.
+ return content::BuildUserAgentFromProduct("Chrome");
+}
+
+base::string16 ShellContentClient::GetLocalizedString(int message_id) const {
+ return l10n_util::GetStringUTF16(message_id);
+}
+
+base::StringPiece ShellContentClient::GetDataResource(
+ int resource_id,
+ ui::ScaleFactor scale_factor) const {
+ return ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
+ resource_id, scale_factor);
+}
+
+base::RefCountedStaticMemory* ShellContentClient::GetDataResourceBytes(
+ int resource_id) const {
+ return ResourceBundle::GetSharedInstance().LoadDataResourceBytes(resource_id);
+}
+
+gfx::Image& ShellContentClient::GetNativeImageNamed(int resource_id) const {
+ return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
+}
+
+} // namespace extensions
diff --git a/extensions/shell/common/shell_content_client.h b/extensions/shell/common/shell_content_client.h
new file mode 100644
index 0000000..f0a722e
--- /dev/null
+++ b/extensions/shell/common/shell_content_client.h
@@ -0,0 +1,33 @@
+// 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 EXTENSIONS_SHELL_COMMON_SHELL_CONTENT_CLIENT_H_
+#define EXTENSIONS_SHELL_COMMON_SHELL_CONTENT_CLIENT_H_
+
+#include "base/compiler_specific.h"
+#include "content/public/common/content_client.h"
+
+namespace extensions {
+
+class ShellContentClient : public content::ContentClient {
+ public:
+ ShellContentClient();
+ virtual ~ShellContentClient();
+
+ virtual void AddAdditionalSchemes(
+ std::vector<std::string>* standard_schemes,
+ std::vector<std::string>* saveable_shemes) OVERRIDE;
+ virtual std::string GetUserAgent() const OVERRIDE;
+ virtual base::string16 GetLocalizedString(int message_id) const OVERRIDE;
+ virtual base::StringPiece GetDataResource(
+ int resource_id,
+ ui::ScaleFactor scale_factor) const OVERRIDE;
+ virtual base::RefCountedStaticMemory* GetDataResourceBytes(
+ int resource_id) const OVERRIDE;
+ virtual gfx::Image& GetNativeImageNamed(int resource_id) const OVERRIDE;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_COMMON_SHELL_CONTENT_CLIENT_H_
diff --git a/extensions/shell/common/shell_extensions_client.cc b/extensions/shell/common/shell_extensions_client.cc
new file mode 100644
index 0000000..0c5844f
--- /dev/null
+++ b/extensions/shell/common/shell_extensions_client.cc
@@ -0,0 +1,204 @@
+// 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 "extensions/shell/common/shell_extensions_client.h"
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "extensions/common/api/generated_schemas.h"
+#include "extensions/common/api/sockets/sockets_manifest_handler.h"
+#include "extensions/common/common_manifest_handlers.h"
+#include "extensions/common/features/api_feature.h"
+#include "extensions/common/features/base_feature_provider.h"
+#include "extensions/common/features/json_feature_provider_source.h"
+#include "extensions/common/features/manifest_feature.h"
+#include "extensions/common/features/permission_feature.h"
+#include "extensions/common/features/simple_feature.h"
+#include "extensions/common/manifest_handler.h"
+#include "extensions/common/permissions/permission_message_provider.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/permissions_provider.h"
+#include "extensions/common/url_pattern_set.h"
+#include "extensions/shell/common/api/generated_schemas.h"
+#include "grit/app_shell_resources.h"
+#include "grit/extensions_resources.h"
+
+namespace extensions {
+
+namespace {
+
+template <class FeatureClass>
+SimpleFeature* CreateFeature() {
+ return new FeatureClass;
+}
+
+// TODO(jamescook): Refactor ChromePermissionsMessageProvider so we can share
+// code. For now, this implementation does nothing.
+class ShellPermissionMessageProvider : public PermissionMessageProvider {
+ public:
+ ShellPermissionMessageProvider() {}
+ virtual ~ShellPermissionMessageProvider() {}
+
+ // PermissionMessageProvider implementation.
+ virtual PermissionMessages GetPermissionMessages(
+ const PermissionSet* permissions,
+ Manifest::Type extension_type) const OVERRIDE {
+ return PermissionMessages();
+ }
+
+ virtual std::vector<base::string16> GetWarningMessages(
+ const PermissionSet* permissions,
+ Manifest::Type extension_type) const OVERRIDE {
+ return std::vector<base::string16>();
+ }
+
+ virtual std::vector<base::string16> GetWarningMessagesDetails(
+ const PermissionSet* permissions,
+ Manifest::Type extension_type) const OVERRIDE {
+ return std::vector<base::string16>();
+ }
+
+ virtual bool IsPrivilegeIncrease(
+ const PermissionSet* old_permissions,
+ const PermissionSet* new_permissions,
+ Manifest::Type extension_type) const OVERRIDE {
+ // Ensure we implement this before shipping.
+ CHECK(false);
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellPermissionMessageProvider);
+};
+
+base::LazyInstance<ShellPermissionMessageProvider>
+ g_permission_message_provider = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+ShellExtensionsClient::ShellExtensionsClient()
+ : extensions_api_permissions_(ExtensionsAPIPermissions()) {
+}
+
+ShellExtensionsClient::~ShellExtensionsClient() {
+}
+
+void ShellExtensionsClient::Initialize() {
+ RegisterCommonManifestHandlers();
+
+ // TODO(rockot): API manifest handlers which move out to src/extensions
+ // should either end up in RegisterCommonManifestHandlers or some new
+ // initialization step specifically for API manifest handlers.
+ (new SocketsManifestHandler)->Register();
+
+ ManifestHandler::FinalizeRegistration();
+ // TODO(jamescook): Do we need to whitelist any extensions?
+
+ PermissionsInfo::GetInstance()->AddProvider(extensions_api_permissions_);
+}
+
+const PermissionMessageProvider&
+ShellExtensionsClient::GetPermissionMessageProvider() const {
+ NOTIMPLEMENTED();
+ return g_permission_message_provider.Get();
+}
+
+scoped_ptr<FeatureProvider> ShellExtensionsClient::CreateFeatureProvider(
+ const std::string& name) const {
+ scoped_ptr<FeatureProvider> provider;
+ scoped_ptr<JSONFeatureProviderSource> source(
+ CreateFeatureProviderSource(name));
+ if (name == "api") {
+ provider.reset(new BaseFeatureProvider(source->dictionary(),
+ CreateFeature<APIFeature>));
+ } else if (name == "manifest") {
+ provider.reset(new BaseFeatureProvider(source->dictionary(),
+ CreateFeature<ManifestFeature>));
+ } else if (name == "permission") {
+ provider.reset(new BaseFeatureProvider(source->dictionary(),
+ CreateFeature<PermissionFeature>));
+ } else {
+ NOTREACHED();
+ }
+ return provider.Pass();
+}
+
+scoped_ptr<JSONFeatureProviderSource>
+ShellExtensionsClient::CreateFeatureProviderSource(
+ const std::string& name) const {
+ scoped_ptr<JSONFeatureProviderSource> source(
+ new JSONFeatureProviderSource(name));
+ if (name == "api") {
+ source->LoadJSON(IDR_EXTENSION_API_FEATURES);
+ source->LoadJSON(IDR_SHELL_EXTENSION_API_FEATURES);
+ } else if (name == "manifest") {
+ source->LoadJSON(IDR_EXTENSION_MANIFEST_FEATURES);
+ } else if (name == "permission") {
+ source->LoadJSON(IDR_EXTENSION_PERMISSION_FEATURES);
+ } else {
+ NOTREACHED();
+ source.reset();
+ }
+ return source.Pass();
+}
+
+void ShellExtensionsClient::FilterHostPermissions(
+ const URLPatternSet& hosts,
+ URLPatternSet* new_hosts,
+ std::set<PermissionMessage>* messages) const {
+ NOTIMPLEMENTED();
+}
+
+void ShellExtensionsClient::SetScriptingWhitelist(
+ const ScriptingWhitelist& whitelist) {
+ scripting_whitelist_ = whitelist;
+}
+
+const ExtensionsClient::ScriptingWhitelist&
+ShellExtensionsClient::GetScriptingWhitelist() const {
+ // TODO(jamescook): Real whitelist.
+ return scripting_whitelist_;
+}
+
+URLPatternSet ShellExtensionsClient::GetPermittedChromeSchemeHosts(
+ const Extension* extension,
+ const APIPermissionSet& api_permissions) const {
+ NOTIMPLEMENTED();
+ return URLPatternSet();
+}
+
+bool ShellExtensionsClient::IsScriptableURL(const GURL& url,
+ std::string* error) const {
+ NOTIMPLEMENTED();
+ return true;
+}
+
+bool ShellExtensionsClient::IsAPISchemaGenerated(
+ const std::string& name) const {
+ // TODO(rockot): Remove dependency on src/chrome once we have some core APIs
+ // moved out. See http://crbug.com/349042.
+ // Special-case our simplified app.runtime implementation because we don't
+ // have the Chrome app APIs available.
+ return core_api::GeneratedSchemas::IsGenerated(name) ||
+ shell_api::GeneratedSchemas::IsGenerated(name);
+}
+
+base::StringPiece ShellExtensionsClient::GetAPISchema(
+ const std::string& name) const {
+ // Schema for chrome.shell APIs.
+ if (shell_api::GeneratedSchemas::IsGenerated(name))
+ return shell_api::GeneratedSchemas::Get(name);
+
+ return core_api::GeneratedSchemas::Get(name);
+}
+
+void ShellExtensionsClient::RegisterAPISchemaResources(
+ ExtensionAPI* api) const {
+}
+
+bool ShellExtensionsClient::ShouldSuppressFatalErrors() const {
+ return true;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/common/shell_extensions_client.h b/extensions/shell/common/shell_extensions_client.h
new file mode 100644
index 0000000..81c5c60
--- /dev/null
+++ b/extensions/shell/common/shell_extensions_client.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 EXTENSIONS_SHELL_COMMON_SHELL_EXTENSIONS_CLIENT_H_
+#define EXTENSIONS_SHELL_COMMON_SHELL_EXTENSIONS_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "extensions/common/extensions_client.h"
+#include "extensions/common/permissions/extensions_api_permissions.h"
+
+namespace extensions {
+
+// The app_shell implementation of ExtensionsClient.
+class ShellExtensionsClient : public ExtensionsClient {
+ public:
+ ShellExtensionsClient();
+ virtual ~ShellExtensionsClient();
+
+ // ExtensionsClient overrides:
+ virtual void Initialize() OVERRIDE;
+ virtual const PermissionMessageProvider& GetPermissionMessageProvider()
+ const OVERRIDE;
+ virtual scoped_ptr<FeatureProvider> CreateFeatureProvider(
+ const std::string& name) const OVERRIDE;
+ virtual scoped_ptr<JSONFeatureProviderSource> CreateFeatureProviderSource(
+ const std::string& name) const OVERRIDE;
+ virtual void FilterHostPermissions(
+ const URLPatternSet& hosts,
+ URLPatternSet* new_hosts,
+ std::set<PermissionMessage>* messages) const OVERRIDE;
+ virtual void SetScriptingWhitelist(
+ const ScriptingWhitelist& whitelist) OVERRIDE;
+ virtual const ScriptingWhitelist& GetScriptingWhitelist() const OVERRIDE;
+ virtual URLPatternSet GetPermittedChromeSchemeHosts(
+ const Extension* extension,
+ const APIPermissionSet& api_permissions) const OVERRIDE;
+ virtual bool IsScriptableURL(const GURL& url,
+ std::string* error) const OVERRIDE;
+ virtual bool IsAPISchemaGenerated(const std::string& name) const OVERRIDE;
+ virtual base::StringPiece GetAPISchema(
+ const std::string& name) const OVERRIDE;
+ virtual void RegisterAPISchemaResources(ExtensionAPI* api) const OVERRIDE;
+ virtual bool ShouldSuppressFatalErrors() const OVERRIDE;
+
+ private:
+ const ExtensionsAPIPermissions extensions_api_permissions_;
+
+ ScriptingWhitelist scripting_whitelist_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellExtensionsClient);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_COMMON_SHELL_EXTENSIONS_CLIENT_H_
diff --git a/extensions/shell/common/switches.cc b/extensions/shell/common/switches.cc
new file mode 100644
index 0000000..0186422
--- /dev/null
+++ b/extensions/shell/common/switches.cc
@@ -0,0 +1,20 @@
+// 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 "extensions/shell/common/switches.h"
+
+namespace extensions {
+namespace switches {
+
+// Path to an app to load at startup.
+const char kAppShellAppPath[] = "app-shell-app-path";
+
+// Bounds for the host window to create (i.e. "800x600").
+const char kAppShellHostWindowBounds[] = "app-shell-host-window-bounds";
+
+// SSID of the preferred WiFi network.
+const char kAppShellPreferredNetwork[] = "app-shell-preferred-network";
+
+} // namespace switches
+} // namespace extensions
diff --git a/extensions/shell/common/switches.h b/extensions/shell/common/switches.h
new file mode 100644
index 0000000..6c4911d
--- /dev/null
+++ b/extensions/shell/common/switches.h
@@ -0,0 +1,20 @@
+// 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 EXTENSIONS_SHELL_COMMON_SWITCHES_H_
+#define EXTENSIONS_SHELL_COMMON_SWITCHES_H_
+
+namespace extensions {
+namespace switches {
+
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
+extern const char kAppShellAppPath[];
+extern const char kAppShellHostWindowBounds[];
+extern const char kAppShellPreferredNetwork[];
+
+} // namespace switches
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_COMMON_SWITCHES_H_
diff --git a/extensions/shell/renderer/DEPS b/extensions/shell/renderer/DEPS
new file mode 100644
index 0000000..baafcac
--- /dev/null
+++ b/extensions/shell/renderer/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ # Only allow includes the renderer can use.
+ "+content/public/renderer",
+
+ "+third_party/WebKit/public",
+ "+v8/include",
+]
diff --git a/extensions/shell/renderer/shell_content_renderer_client.cc b/extensions/shell/renderer/shell_content_renderer_client.cc
new file mode 100644
index 0000000..c7a9be6
--- /dev/null
+++ b/extensions/shell/renderer/shell_content_renderer_client.cc
@@ -0,0 +1,131 @@
+// 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 "extensions/shell/renderer/shell_content_renderer_client.h"
+
+#include "content/public/renderer/render_frame.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "content/public/renderer/render_frame_observer_tracker.h"
+#include "content/public/renderer/render_thread.h"
+#include "extensions/common/extensions_client.h"
+#include "extensions/renderer/dispatcher.h"
+#include "extensions/renderer/extension_helper.h"
+#include "extensions/shell/common/shell_extensions_client.h"
+#include "extensions/shell/renderer/shell_dispatcher_delegate.h"
+#include "extensions/shell/renderer/shell_extensions_renderer_client.h"
+#include "extensions/shell/renderer/shell_renderer_main_delegate.h"
+
+using blink::WebFrame;
+using blink::WebString;
+using content::RenderThread;
+
+namespace extensions {
+
+namespace {
+
+// TODO: promote ExtensionFrameHelper to a common place and share with this.
+class ShellFrameHelper
+ : public content::RenderFrameObserver,
+ public content::RenderFrameObserverTracker<ShellFrameHelper> {
+ public:
+ ShellFrameHelper(content::RenderFrame* render_frame,
+ Dispatcher* extension_dispatcher);
+ virtual ~ShellFrameHelper();
+
+ // RenderFrameObserver implementation.
+ virtual void WillReleaseScriptContext(v8::Handle<v8::Context>,
+ int world_id) OVERRIDE;
+
+ private:
+ Dispatcher* extension_dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellFrameHelper);
+};
+
+ShellFrameHelper::ShellFrameHelper(content::RenderFrame* render_frame,
+ Dispatcher* extension_dispatcher)
+ : content::RenderFrameObserver(render_frame),
+ content::RenderFrameObserverTracker<ShellFrameHelper>(render_frame),
+ extension_dispatcher_(extension_dispatcher) {
+}
+
+ShellFrameHelper::~ShellFrameHelper() {
+}
+
+void ShellFrameHelper::WillReleaseScriptContext(v8::Handle<v8::Context> context,
+ int world_id) {
+ extension_dispatcher_->WillReleaseScriptContext(
+ render_frame()->GetWebFrame(), context, world_id);
+}
+
+} // namespace
+
+ShellContentRendererClient::ShellContentRendererClient(
+ scoped_ptr<ShellRendererMainDelegate> delegate)
+ : delegate_(delegate.Pass()) {
+}
+
+ShellContentRendererClient::~ShellContentRendererClient() {
+}
+
+void ShellContentRendererClient::RenderThreadStarted() {
+ RenderThread* thread = RenderThread::Get();
+
+ extensions_client_.reset(new ShellExtensionsClient);
+ ExtensionsClient::Set(extensions_client_.get());
+
+ extensions_renderer_client_.reset(new ShellExtensionsRendererClient);
+ ExtensionsRendererClient::Set(extensions_renderer_client_.get());
+
+ extension_dispatcher_delegate_.reset(new ShellDispatcherDelegate());
+
+ // Must be initialized after ExtensionsRendererClient.
+ extension_dispatcher_.reset(
+ new Dispatcher(extension_dispatcher_delegate_.get()));
+ thread->AddObserver(extension_dispatcher_.get());
+
+ // TODO(jamescook): Init WebSecurityPolicy for chrome-extension: schemes.
+ // See ChromeContentRendererClient for details.
+ if (delegate_)
+ delegate_->OnThreadStarted(thread);
+}
+
+void ShellContentRendererClient::RenderFrameCreated(
+ content::RenderFrame* render_frame) {
+ // ShellFrameHelper destroyes itself when the RenderFrame is destroyed.
+ new ShellFrameHelper(render_frame, extension_dispatcher_.get());
+}
+
+void ShellContentRendererClient::RenderViewCreated(
+ content::RenderView* render_view) {
+ new ExtensionHelper(render_view, extension_dispatcher_.get());
+ if (delegate_)
+ delegate_->OnViewCreated(render_view);
+}
+
+bool ShellContentRendererClient::WillSendRequest(
+ blink::WebFrame* frame,
+ content::PageTransition transition_type,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ GURL* new_url) {
+ // TODO(jamescook): Cause an error for bad extension scheme requests?
+ return false;
+}
+
+void ShellContentRendererClient::DidCreateScriptContext(
+ WebFrame* frame,
+ v8::Handle<v8::Context> context,
+ int extension_group,
+ int world_id) {
+ extension_dispatcher_->DidCreateScriptContext(
+ frame, context, extension_group, world_id);
+}
+
+bool ShellContentRendererClient::ShouldEnableSiteIsolationPolicy() const {
+ // Extension renderers don't need site isolation.
+ return false;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/renderer/shell_content_renderer_client.h b/extensions/shell/renderer/shell_content_renderer_client.h
new file mode 100644
index 0000000..e7a1fbc
--- /dev/null
+++ b/extensions/shell/renderer/shell_content_renderer_client.h
@@ -0,0 +1,55 @@
+// 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 EXTENSIONS_SHELL_RENDERER_SHELL_CONTENT_RENDERER_CLIENT_H_
+#define EXTENSIONS_SHELL_RENDERER_SHELL_CONTENT_RENDERER_CLIENT_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/renderer/content_renderer_client.h"
+
+namespace extensions {
+
+class Dispatcher;
+class DispatcherDelegate;
+class ShellExtensionsClient;
+class ShellExtensionsRendererClient;
+class ShellRendererMainDelegate;
+
+// Renderer initialization and runtime support for app_shell.
+class ShellContentRendererClient : public content::ContentRendererClient {
+ public:
+ explicit ShellContentRendererClient(
+ scoped_ptr<ShellRendererMainDelegate> delegate);
+ virtual ~ShellContentRendererClient();
+
+ // content::ContentRendererClient implementation:
+ virtual void RenderThreadStarted() OVERRIDE;
+ virtual void RenderFrameCreated(content::RenderFrame* render_frame) OVERRIDE;
+ virtual void RenderViewCreated(content::RenderView* render_view) OVERRIDE;
+ virtual bool WillSendRequest(blink::WebFrame* frame,
+ content::PageTransition transition_type,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ GURL* new_url) OVERRIDE;
+ virtual void DidCreateScriptContext(blink::WebFrame* frame,
+ v8::Handle<v8::Context> context,
+ int extension_group,
+ int world_id) OVERRIDE;
+ virtual bool ShouldEnableSiteIsolationPolicy() const OVERRIDE;
+
+ private:
+ scoped_ptr<ShellRendererMainDelegate> delegate_;
+ scoped_ptr<ShellExtensionsClient> extensions_client_;
+ scoped_ptr<ShellExtensionsRendererClient> extensions_renderer_client_;
+ scoped_ptr<DispatcherDelegate> extension_dispatcher_delegate_;
+ scoped_ptr<Dispatcher> extension_dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellContentRendererClient);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_RENDERER_SHELL_CONTENT_RENDERER_CLIENT_H_
diff --git a/extensions/shell/renderer/shell_custom_bindings.cc b/extensions/shell/renderer/shell_custom_bindings.cc
new file mode 100644
index 0000000..40965ca
--- /dev/null
+++ b/extensions/shell/renderer/shell_custom_bindings.cc
@@ -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.
+
+#include "extensions/shell/renderer/shell_custom_bindings.h"
+
+#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/v8_value_converter.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/renderer/script_context.h"
+#include "extensions/renderer/script_context_set.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "v8/include/v8.h"
+
+namespace extensions {
+
+ShellCustomBindings::ShellCustomBindings(ScriptContext* context)
+ : ObjectBackedNativeHandler(context) {
+ RouteFunction(
+ "GetView",
+ base::Bind(&ShellCustomBindings::GetView, base::Unretained(this)));
+}
+
+void ShellCustomBindings::GetView(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 1 || !args[0]->IsInt32())
+ return;
+
+ int view_id = args[0]->Int32Value();
+ if (view_id == MSG_ROUTING_NONE)
+ return;
+
+ content::RenderView* view = content::RenderView::FromRoutingID(view_id);
+ if (!view)
+ return;
+
+ // Set the opener so we have a security origin set up before returning the DOM
+ // reference.
+ content::RenderView* render_view = context()->GetRenderView();
+ if (!render_view)
+ return;
+ blink::WebFrame* opener = render_view->GetWebView()->mainFrame();
+ blink::WebFrame* frame = view->GetWebView()->mainFrame();
+ frame->setOpener(opener);
+
+ // Resume resource requests.
+ content::RenderThread::Get()->Send(
+ new ExtensionHostMsg_ResumeRequests(view->GetRoutingID()));
+
+ // Return the script context.
+ v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global();
+ args.GetReturnValue().Set(window);
+}
+
+} // namespace extensions
diff --git a/extensions/shell/renderer/shell_custom_bindings.h b/extensions/shell/renderer/shell_custom_bindings.h
new file mode 100644
index 0000000..aaa4abe
--- /dev/null
+++ b/extensions/shell/renderer/shell_custom_bindings.h
@@ -0,0 +1,25 @@
+// 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 EXTENSIONS_SHELL_RENDERER_SHELL_CUSTOM_BINDINGS_H_
+#define EXTENSIONS_SHELL_RENDERER_SHELL_CUSTOM_BINDINGS_H_
+
+#include "extensions/renderer/object_backed_native_handler.h"
+
+namespace extensions {
+
+// Implements custom bindings for the chrome.shell API.
+class ShellCustomBindings : public ObjectBackedNativeHandler {
+ public:
+ ShellCustomBindings(ScriptContext* context);
+
+ private:
+ void GetView(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ DISALLOW_COPY_AND_ASSIGN(ShellCustomBindings);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_RENDERER_SHELL_CUSTOM_BINDINGS_H_
diff --git a/extensions/shell/renderer/shell_custom_bindings.js b/extensions/shell/renderer/shell_custom_bindings.js
new file mode 100644
index 0000000..5fe9a9ae
--- /dev/null
+++ b/extensions/shell/renderer/shell_custom_bindings.js
@@ -0,0 +1,78 @@
+// 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.
+
+var shellNatives = requireNative('shell_natives');
+var Binding = require('binding').Binding;
+var forEach = require('utils').forEach;
+var renderViewObserverNatives = requireNative('renderViewObserverNatives');
+
+var currentAppWindow = null;
+
+var shell = Binding.create('shell');
+shell.registerCustomHook(function(bindingsAPI) {
+ var apiFunctions = bindingsAPI.apiFunctions;
+
+ apiFunctions.setCustomCallback('createWindow',
+ function(name, request, windowParams) {
+ var view = null;
+
+ // When window creation fails, |windowParams| will be undefined.
+ if (windowParams && windowParams.viewId) {
+ view = shellNatives.GetView(windowParams.viewId);
+ }
+
+ if (!view) {
+ // No route to created window. If given a callback, trigger it with an
+ // undefined object.
+ if (request.callback) {
+ request.callback(undefined);
+ delete request.callback;
+ }
+ return;
+ }
+
+ // Initialize the app window in the newly created JS context
+ view.chrome.shell.initializeAppWindow();
+
+ var callback = request.callback;
+ if (callback) {
+ delete request.callback;
+
+ var willCallback =
+ renderViewObserverNatives.OnDocumentElementCreated(
+ windowParams.viewId,
+ function(success) {
+ if (success) {
+ callback(view.chrome.shell.currentWindow());
+ } else {
+ callback(undefined);
+ }
+ });
+ if (!willCallback) {
+ callback(undefined);
+ }
+ }
+ });
+
+ apiFunctions.setHandleRequest('currentWindow', function() {
+ if (!currentAppWindow) {
+ console.error(
+ 'The JavaScript context calling chrome.shell.currentWindow() has' +
+ ' no associated AppWindow.');
+ return null;
+ }
+ return currentAppWindow;
+ });
+
+ // This is an internal function, but needs to be bound into a closure
+ // so the correct JS context is used for global variables such as
+ // currentAppWindow.
+ apiFunctions.setHandleRequest('initializeAppWindow', function() {
+ var AppWindow = function() {};
+ AppWindow.prototype.contentWindow = window;
+ currentAppWindow = new AppWindow;
+ });
+});
+
+exports.binding = shell.generate();
diff --git a/extensions/shell/renderer/shell_dispatcher_delegate.cc b/extensions/shell/renderer/shell_dispatcher_delegate.cc
new file mode 100644
index 0000000..0f6b04b
--- /dev/null
+++ b/extensions/shell/renderer/shell_dispatcher_delegate.cc
@@ -0,0 +1,35 @@
+// 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 "extensions/shell/renderer/shell_dispatcher_delegate.h"
+
+#include "extensions/renderer/module_system.h"
+#include "extensions/renderer/resource_bundle_source_map.h"
+#include "extensions/renderer/script_context.h"
+#include "extensions/shell/renderer/shell_custom_bindings.h"
+#include "grit/app_shell_resources.h"
+
+namespace extensions {
+
+ShellDispatcherDelegate::ShellDispatcherDelegate() {
+}
+
+ShellDispatcherDelegate::~ShellDispatcherDelegate() {
+}
+
+void ShellDispatcherDelegate::RegisterNativeHandlers(
+ Dispatcher* dispatcher,
+ ModuleSystem* module_system,
+ ScriptContext* context) {
+ module_system->RegisterNativeHandler(
+ "shell_natives",
+ scoped_ptr<NativeHandler>(new ShellCustomBindings(context)));
+}
+
+void ShellDispatcherDelegate::PopulateSourceMap(
+ ResourceBundleSourceMap* source_map) {
+ source_map->RegisterSource("shell", IDR_SHELL_CUSTOM_BINDINGS_JS);
+}
+
+} // namespace extensions
diff --git a/extensions/shell/renderer/shell_dispatcher_delegate.h b/extensions/shell/renderer/shell_dispatcher_delegate.h
new file mode 100644
index 0000000..5009ce7
--- /dev/null
+++ b/extensions/shell/renderer/shell_dispatcher_delegate.h
@@ -0,0 +1,33 @@
+// 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 EXTENSIONS_SHELL_RENDERER_SHELL_DISPATCHER_DELEGATE_H_
+#define EXTENSIONS_SHELL_RENDERER_SHELL_DISPATCHER_DELEGATE_H_
+
+#include "base/macros.h"
+#include "extensions/renderer/default_dispatcher_delegate.h"
+
+namespace extensions {
+
+// app_shell's implementation of DispatcherDelegate. This inherits the behavior
+// of the default delegate while augmenting its own script resources and native
+// native handlers.
+class ShellDispatcherDelegate : public DefaultDispatcherDelegate {
+ public:
+ ShellDispatcherDelegate();
+ virtual ~ShellDispatcherDelegate();
+
+ // DispatcherDelegate implementation.
+ virtual void RegisterNativeHandlers(Dispatcher* dispatcher,
+ ModuleSystem* module_system,
+ ScriptContext* context) OVERRIDE;
+ virtual void PopulateSourceMap(ResourceBundleSourceMap* source_map) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellDispatcherDelegate);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_RENDERER_SHELL_DISPATCHER_DELEGATE_H_
diff --git a/extensions/shell/renderer/shell_extensions_renderer_client.cc b/extensions/shell/renderer/shell_extensions_renderer_client.cc
new file mode 100644
index 0000000..c3be350
--- /dev/null
+++ b/extensions/shell/renderer/shell_extensions_renderer_client.cc
@@ -0,0 +1,27 @@
+// 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 "extensions/shell/renderer/shell_extensions_renderer_client.h"
+
+namespace extensions {
+
+ShellExtensionsRendererClient::ShellExtensionsRendererClient() {
+}
+
+ShellExtensionsRendererClient::~ShellExtensionsRendererClient() {
+}
+
+bool ShellExtensionsRendererClient::IsIncognitoProcess() const {
+ // app_shell doesn't support off-the-record contexts.
+ return false;
+}
+
+int ShellExtensionsRendererClient::GetLowestIsolatedWorldId() const {
+ // app_shell doesn't need to reserve world IDs for anything other than
+ // extensions, so we always return 1. Note that 0 is reserved for the global
+ // world.
+ return 1;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/renderer/shell_extensions_renderer_client.h b/extensions/shell/renderer/shell_extensions_renderer_client.h
new file mode 100644
index 0000000..1bbe3f4
--- /dev/null
+++ b/extensions/shell/renderer/shell_extensions_renderer_client.h
@@ -0,0 +1,28 @@
+// 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 EXTENSIONS_SHELL_RENDERER_SHELL_EXTENSIONS_RENDERER_CLIENT_H_
+#define EXTENSIONS_SHELL_RENDERER_SHELL_EXTENSIONS_RENDERER_CLIENT_H_
+
+#include "base/macros.h"
+#include "extensions/renderer/extensions_renderer_client.h"
+
+namespace extensions {
+
+class ShellExtensionsRendererClient : public ExtensionsRendererClient {
+ public:
+ ShellExtensionsRendererClient();
+ virtual ~ShellExtensionsRendererClient();
+
+ // ExtensionsRendererClient implementation.
+ virtual bool IsIncognitoProcess() const OVERRIDE;
+ virtual int GetLowestIsolatedWorldId() const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellExtensionsRendererClient);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_RENDERER_SHELL_EXTENSIONS_RENDERER_CLIENT_H_
diff --git a/extensions/shell/renderer/shell_renderer_main_delegate.h b/extensions/shell/renderer/shell_renderer_main_delegate.h
new file mode 100644
index 0000000..51396bd
--- /dev/null
+++ b/extensions/shell/renderer/shell_renderer_main_delegate.h
@@ -0,0 +1,30 @@
+// 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 EXTENSIONS_SHELL_RENDERER_SHELL_RENDERER_MAIN_DELEGATE_H_
+#define EXTENSIONS_SHELL_RENDERER_SHELL_RENDERER_MAIN_DELEGATE_H_
+
+namespace content {
+class RenderThread;
+class RenderView;
+}
+
+namespace extensions {
+
+class ShellRendererMainDelegate {
+ public:
+ virtual ~ShellRendererMainDelegate() {}
+
+ // Called when |thread| is started, after the extensions subsystem has been
+ // initialized for |thread|.
+ virtual void OnThreadStarted(content::RenderThread* thread) = 0;
+
+ // Called for each RenderView created in the renderer process, after the
+ // extension related code has been initialized for the view.
+ virtual void OnViewCreated(content::RenderView* view) = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_RENDERER_SHELL_RENDERER_MAIN_DELEGATE_H_
diff --git a/extensions/shell/test/DEPS b/extensions/shell/test/DEPS
new file mode 100644
index 0000000..c243ad4
--- /dev/null
+++ b/extensions/shell/test/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ # Testing utilities can access anything in extensions/shell.
+ "+extensions/shell",
+]
diff --git a/extensions/shell/test/shell_test.cc b/extensions/shell/test/shell_test.cc
new file mode 100644
index 0000000..e67400d
--- /dev/null
+++ b/extensions/shell/test/shell_test.cc
@@ -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.
+
+#include "extensions/shell/test/shell_test.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "content/public/common/content_switches.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/shell/browser/shell_content_browser_client.h"
+#include "extensions/shell/browser/shell_desktop_controller.h"
+#include "extensions/shell/browser/shell_extension_system.h"
+
+namespace extensions {
+
+AppShellTest::AppShellTest() : browser_context_(NULL), extension_system_(NULL) {
+}
+
+AppShellTest::~AppShellTest() {
+}
+
+void AppShellTest::SetUp() {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ command_line->AppendSwitchASCII(switches::kTestType, "appshell");
+ content::BrowserTestBase::SetUp();
+}
+
+void AppShellTest::SetUpOnMainThread() {
+ browser_context_ = ShellContentBrowserClient::Get()->GetBrowserContext();
+
+ extension_system_ = static_cast<ShellExtensionSystem*>(
+ ExtensionSystem::Get(browser_context_));
+}
+
+void AppShellTest::RunTestOnMainThreadLoop() {
+ base::MessageLoopForUI::current()->RunUntilIdle();
+
+ SetUpOnMainThread();
+
+ RunTestOnMainThread();
+
+ TearDownOnMainThread();
+
+ // Clean up the app window.
+ ShellDesktopController::instance()->CloseAppWindows();
+}
+
+bool AppShellTest::LoadAndLaunchApp(const base::FilePath& app_dir) {
+ bool loaded = extension_system_->LoadApp(app_dir);
+ if (loaded)
+ extension_system_->LaunchApp();
+ return loaded;
+}
+
+} // namespace extensions
diff --git a/extensions/shell/test/shell_test.h b/extensions/shell/test/shell_test.h
new file mode 100644
index 0000000..c9d36ed
--- /dev/null
+++ b/extensions/shell/test/shell_test.h
@@ -0,0 +1,48 @@
+// 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 EXTENSIONS_SHELL_TEST_SHELL_TEST_H_
+#define EXTENSIONS_SHELL_TEST_SHELL_TEST_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_base.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+
+class ShellExtensionSystem;
+
+// Base class for app shell browser tests.
+class AppShellTest : public content::BrowserTestBase {
+ public:
+ AppShellTest();
+ virtual ~AppShellTest();
+
+ // content::BrowserTestBase implementation.
+ virtual void SetUp() OVERRIDE;
+ virtual void SetUpOnMainThread() OVERRIDE;
+ virtual void RunTestOnMainThreadLoop() OVERRIDE;
+
+ // Loads an unpacked application from a directory using |extension_system_|
+ // and attempts to launch it. Returns true on success.
+ bool LoadAndLaunchApp(const base::FilePath& app_dir);
+
+ content::BrowserContext* browser_context() { return browser_context_; }
+
+ private:
+ content::BrowserContext* browser_context_;
+ ShellExtensionSystem* extension_system_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_TEST_SHELL_TEST_H_
diff --git a/extensions/shell/test/shell_test_launcher_delegate.cc b/extensions/shell/test/shell_test_launcher_delegate.cc
new file mode 100644
index 0000000..ce7bc59
--- /dev/null
+++ b/extensions/shell/test/shell_test_launcher_delegate.cc
@@ -0,0 +1,27 @@
+// 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 "extensions/shell/test/shell_test_launcher_delegate.h"
+
+#include "base/test/test_suite.h"
+#include "extensions/shell/app/shell_main_delegate.h"
+
+namespace extensions {
+
+int AppShellTestLauncherDelegate::RunTestSuite(int argc, char** argv) {
+ return base::TestSuite(argc, argv).Run();
+}
+
+bool AppShellTestLauncherDelegate::AdjustChildProcessCommandLine(
+ base::CommandLine* command_line,
+ const base::FilePath& temp_data_dir) {
+ return true;
+}
+
+content::ContentMainDelegate*
+AppShellTestLauncherDelegate::CreateContentMainDelegate() {
+ return new ShellMainDelegate();
+}
+
+} // namespace extensions
diff --git a/extensions/shell/test/shell_test_launcher_delegate.h b/extensions/shell/test/shell_test_launcher_delegate.h
new file mode 100644
index 0000000..8e62f5d
--- /dev/null
+++ b/extensions/shell/test/shell_test_launcher_delegate.h
@@ -0,0 +1,23 @@
+// 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 EXTENSIONS_SHELL_TEST_SHELL_TEST_LAUNCHER_DELEGATE_H_
+#define EXTENSIONS_SHELL_TEST_SHELL_TEST_LAUNCHER_DELEGATE_H_
+
+#include "content/public/test/test_launcher.h"
+
+namespace extensions {
+
+class AppShellTestLauncherDelegate : public content::TestLauncherDelegate {
+ public:
+ virtual int RunTestSuite(int argc, char** argv) OVERRIDE;
+ virtual bool AdjustChildProcessCommandLine(
+ base::CommandLine* command_line,
+ const base::FilePath& temp_data_dir) OVERRIDE;
+ virtual content::ContentMainDelegate* CreateContentMainDelegate() OVERRIDE;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_SHELL_TEST_SHELL_TEST_LAUNCHER_DELEGATE_H_
diff --git a/extensions/shell/test/shell_tests_main.cc b/extensions/shell/test/shell_tests_main.cc
new file mode 100644
index 0000000..eb16469
--- /dev/null
+++ b/extensions/shell/test/shell_tests_main.cc
@@ -0,0 +1,15 @@
+// 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 <algorithm>
+
+#include "base/sys_info.h"
+#include "extensions/shell/test/shell_test_launcher_delegate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+int main(int argc, char** argv) {
+ int default_jobs = std::max(1, base::SysInfo::NumberOfProcessors() / 2);
+ extensions::AppShellTestLauncherDelegate launcher_delegate;
+ return content::LaunchTests(&launcher_delegate, default_jobs, argc, argv);
+}