summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-06-20 14:52:04 +0100
committerTorne (Richard Coles) <torne@google.com>2014-06-20 14:52:04 +0100
commitf8ee788a64d60abd8f2d742a5fdedde054ecd910 (patch)
tree7dc14380200b953c64e0ccd16435cdbd1dbf1205 /apps
parentfcbbbe23a38088a52492922075e71a419c4b01ec (diff)
downloadchromium_org-f8ee788a64d60abd8f2d742a5fdedde054ecd910.tar.gz
Merge from Chromium at DEPS revision 278205
This commit was generated by merge_to_master.py. Change-Id: I23f1e7ea8c154ba72e7fb594436216f861f868ab
Diffstat (limited to 'apps')
-rw-r--r--apps/app_restore_service_browsertest.cc13
-rw-r--r--apps/app_shim/app_shim_interactive_uitest_mac.mm307
-rw-r--r--apps/app_shim/chrome_main_app_mode_mac.mm8
-rw-r--r--apps/app_window.cc2
-rw-r--r--apps/apps.gypi4
-rw-r--r--apps/launcher.cc4
-rw-r--r--apps/shell/app/shell_main_delegate.cc9
-rw-r--r--apps/shell/app/shell_main_delegate.h5
-rw-r--r--apps/shell/app_shell.gyp4
-rw-r--r--apps/shell/browser/default_shell_app_window_controller.cc45
-rw-r--r--apps/shell/browser/default_shell_app_window_controller.h40
-rw-r--r--apps/shell/browser/default_shell_browser_main_delegate.cc9
-rw-r--r--apps/shell/browser/shell_app_window_controller.h30
-rw-r--r--apps/shell/browser/shell_browser_main_parts.cc4
-rw-r--r--apps/shell/browser/shell_desktop_controller.cc31
-rw-r--r--apps/shell/browser/shell_desktop_controller.h11
-rw-r--r--apps/shell/browser/shell_extension_system.cc29
-rw-r--r--apps/shell/browser/shell_extension_system.h14
-rw-r--r--apps/shell/browser/shell_network_controller_chromeos.cc2
-rw-r--r--apps/shell/renderer/shell_content_renderer_client.cc10
-rw-r--r--apps/shell/renderer/shell_content_renderer_client.h5
-rw-r--r--apps/shell/renderer/shell_renderer_main_delegate.h30
-rw-r--r--apps/shell/test/shell_test.cc7
23 files changed, 567 insertions, 56 deletions
diff --git a/apps/app_restore_service_browsertest.cc b/apps/app_restore_service_browsertest.cc
index 1ba87e3da6..f66b1bed8b 100644
--- a/apps/app_restore_service_browsertest.cc
+++ b/apps/app_restore_service_browsertest.cc
@@ -125,14 +125,9 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, FileAccessIsSavedToPrefs) {
FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
"temp", temp_directory.path());
- ExtensionTestMessageListener file_written_listener("fileWritten", false);
- ExtensionTestMessageListener access_ok_listener(
- "restartedFileAccessOK", false);
-
- const Extension* extension =
- LoadAndLaunchPlatformApp("file_access_saved_to_prefs_test");
+ const Extension* extension = LoadAndLaunchPlatformApp(
+ "file_access_saved_to_prefs_test", "fileWritten");
ASSERT_TRUE(extension);
- file_written_listener.WaitUntilSatisfied();
SavedFilesService* saved_files_service = SavedFilesService::Get(profile());
@@ -170,14 +165,12 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_FileAccessIsRestored) {
FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
"temp", temp_directory.path());
- ExtensionTestMessageListener file_written_listener("fileWritten", false);
ExtensionTestMessageListener access_ok_listener(
"restartedFileAccessOK", false);
const Extension* extension =
- LoadAndLaunchPlatformApp("file_access_restored_test");
+ LoadAndLaunchPlatformApp("file_access_restored_test", "fileWritten");
ASSERT_TRUE(extension);
- file_written_listener.WaitUntilSatisfied();
ExtensionPrefs* extension_prefs =
ExtensionPrefs::Get(browser()->profile());
diff --git a/apps/app_shim/app_shim_interactive_uitest_mac.mm b/apps/app_shim/app_shim_interactive_uitest_mac.mm
new file mode 100644
index 0000000000..1cfdf7953d
--- /dev/null
+++ b/apps/app_shim/app_shim_interactive_uitest_mac.mm
@@ -0,0 +1,307 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+#include <vector>
+
+#include "apps/app_shim/app_shim_handler_mac.h"
+#include "apps/app_shim/app_shim_host_manager_mac.h"
+#include "apps/app_shim/extension_app_shim_handler_mac.h"
+#include "apps/switches.h"
+#include "apps/ui/native_app_window.h"
+#include "base/auto_reset.h"
+#include "base/callback.h"
+#include "base/files/file_path_watcher.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/launch_services_util.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/path_service.h"
+#include "base/process/launch.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/test/test_timeouts.h"
+#include "chrome/browser/apps/app_browsertest_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_applications/web_app_mac.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/mac/app_mode_common.h"
+#include "content/public/test/test_utils.h"
+#include "extensions/browser/extension_registry.h"
+#import "ui/events/test/cocoa_test_event_utils.h"
+
+namespace {
+
+// General end-to-end test for app shims.
+class AppShimInteractiveTest : public extensions::PlatformAppBrowserTest {
+ protected:
+ AppShimInteractiveTest()
+ : auto_reset_(&g_app_shims_allow_update_and_launch_in_tests, true) {}
+
+ private:
+ // Temporarily enable app shims.
+ base::AutoReset<bool> auto_reset_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppShimInteractiveTest);
+};
+
+// Watches for changes to a file. This is designed to be used from the the UI
+// thread.
+class WindowedFilePathWatcher
+ : public base::RefCountedThreadSafe<WindowedFilePathWatcher> {
+ public:
+ WindowedFilePathWatcher(const base::FilePath& path) : observed_(false) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&WindowedFilePathWatcher::Watch, this, path));
+ }
+
+ void Wait() {
+ if (observed_)
+ return;
+
+ run_loop_.reset(new base::RunLoop);
+ run_loop_->Run();
+ }
+
+ protected:
+ friend class base::RefCountedThreadSafe<WindowedFilePathWatcher>;
+ virtual ~WindowedFilePathWatcher() {}
+
+ void Watch(const base::FilePath& path) {
+ watcher_.Watch(
+ path, false, base::Bind(&WindowedFilePathWatcher::Observe, this));
+ }
+
+ void Observe(const base::FilePath& path, bool error) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&WindowedFilePathWatcher::StopRunLoop, this));
+ }
+
+ void StopRunLoop() {
+ observed_ = true;
+ if (run_loop_.get())
+ run_loop_->Quit();
+ }
+
+ private:
+ base::FilePathWatcher watcher_;
+ bool observed_;
+ scoped_ptr<base::RunLoop> run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowedFilePathWatcher);
+};
+
+// Watches for an app shim to connect.
+class WindowedAppShimLaunchObserver : public apps::AppShimHandler {
+ public:
+ WindowedAppShimLaunchObserver(const std::string& app_id)
+ : app_mode_id_(app_id),
+ observed_(false) {
+ apps::AppShimHandler::RegisterHandler(app_id, this);
+ }
+
+ void Wait() {
+ if (observed_)
+ return;
+
+ run_loop_.reset(new base::RunLoop);
+ run_loop_->Run();
+ }
+
+ // AppShimHandler overrides:
+ virtual void OnShimLaunch(Host* host,
+ apps::AppShimLaunchType launch_type,
+ const std::vector<base::FilePath>& files) OVERRIDE {
+ // Remove self and pass through to the default handler.
+ apps::AppShimHandler::RemoveHandler(app_mode_id_);
+ apps::AppShimHandler::GetForAppMode(app_mode_id_)
+ ->OnShimLaunch(host, launch_type, files);
+ observed_ = true;
+ if (run_loop_.get())
+ run_loop_->Quit();
+ }
+ virtual void OnShimClose(Host* host) OVERRIDE {}
+ virtual void OnShimFocus(Host* host,
+ apps::AppShimFocusType focus_type,
+ const std::vector<base::FilePath>& files) OVERRIDE {}
+ virtual void OnShimSetHidden(Host* host, bool hidden) OVERRIDE {}
+ virtual void OnShimQuit(Host* host) OVERRIDE {}
+
+ private:
+ std::string app_mode_id_;
+ bool observed_;
+ scoped_ptr<base::RunLoop> run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowedAppShimLaunchObserver);
+};
+
+NSString* GetBundleID(const base::FilePath& shim_path) {
+ base::FilePath plist_path = shim_path.Append("Contents").Append("Info.plist");
+ NSMutableDictionary* plist = [NSMutableDictionary
+ dictionaryWithContentsOfFile:base::mac::FilePathToNSString(plist_path)];
+ return [plist objectForKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)];
+}
+
+bool HasAppShimHost(Profile* profile, const std::string& app_id) {
+ return g_browser_process->platform_part()
+ ->app_shim_host_manager()
+ ->extension_app_shim_handler()
+ ->FindHost(profile, app_id);
+}
+
+} // namespace
+
+// Watches for NSNotifications from the shared workspace.
+@interface WindowedNSNotificationObserver : NSObject {
+ @private
+ base::scoped_nsobject<NSString> bundleId_;
+ BOOL notificationReceived_;
+ scoped_ptr<base::RunLoop> runLoop_;
+}
+
+- (id)initForNotification:(NSString*)name
+ andBundleId:(NSString*)bundleId;
+- (void)observe:(NSNotification*)notification;
+- (void)wait;
+@end
+
+@implementation WindowedNSNotificationObserver
+
+- (id)initForNotification:(NSString*)name
+ andBundleId:(NSString*)bundleId {
+ if (self = [super init]) {
+ bundleId_.reset([[bundleId copy] retain]);
+ [[[NSWorkspace sharedWorkspace] notificationCenter]
+ addObserver:self
+ selector:@selector(observe:)
+ name:name
+ object:nil];
+ }
+ return self;
+}
+
+- (void)observe:(NSNotification*)notification {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ NSRunningApplication* application =
+ [[notification userInfo] objectForKey:NSWorkspaceApplicationKey];
+ if (![[application bundleIdentifier] isEqualToString:bundleId_])
+ return;
+
+ [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
+ notificationReceived_ = YES;
+ if (runLoop_.get())
+ runLoop_->Quit();
+}
+
+- (void)wait {
+ if (notificationReceived_)
+ return;
+
+ runLoop_.reset(new base::RunLoop);
+ runLoop_->Run();
+}
+
+@end
+
+namespace apps {
+
+// Shims require static libraries http://crbug.com/386024.
+#if defined(COMPONENT_BUILD)
+#define MAYBE_Launch DISABLED_Launch
+#else
+#define MAYBE_Launch Launch
+#endif
+
+// Test that launching the shim for an app starts the app, and vice versa.
+// These two cases are combined because the time to run the test is dominated
+// by loading the extension and creating the shim.
+IN_PROC_BROWSER_TEST_F(AppShimInteractiveTest, MAYBE_Launch) {
+ // Install the app.
+ const extensions::Extension* app = InstallPlatformApp("minimal");
+
+ // Use a WebAppShortcutCreator to get the path.
+ web_app::WebAppShortcutCreator shortcut_creator(
+ web_app::GetWebAppDataDirectory(profile()->GetPath(), app->id(), GURL()),
+ web_app::ShortcutInfoForExtensionAndProfile(app, profile()),
+ extensions::FileHandlersInfo());
+ base::FilePath shim_path = shortcut_creator.GetInternalShortcutPath();
+ EXPECT_FALSE(base::PathExists(shim_path));
+
+ // Create the internal app shim by simulating an app update. FilePathWatcher
+ // is used to wait for file operations on the shim to be finished before
+ // attempting to launch it. Since all of the file operations are done in the
+ // same event on the FILE thread, everything will be done by the time the
+ // watcher's callback is executed.
+ scoped_refptr<WindowedFilePathWatcher> file_watcher =
+ new WindowedFilePathWatcher(shim_path);
+ web_app::UpdateAllShortcuts(base::string16(), profile(), app);
+ file_watcher->Wait();
+ NSString* bundle_id = GetBundleID(shim_path);
+
+ // Case 1: Launch the shim, it should start the app.
+ {
+ ExtensionTestMessageListener launched_listener("Launched", false);
+ CommandLine shim_cmdline(CommandLine::NO_PROGRAM);
+ shim_cmdline.AppendSwitch(app_mode::kLaunchedForTest);
+ ProcessSerialNumber shim_psn;
+ ASSERT_TRUE(base::mac::OpenApplicationWithPath(
+ shim_path, shim_cmdline, kLSLaunchDefaults, &shim_psn));
+ ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
+
+ ASSERT_TRUE(GetFirstAppWindow());
+ EXPECT_TRUE(HasAppShimHost(profile(), app->id()));
+
+ // If the window is closed, the shim should quit.
+ pid_t shim_pid;
+ EXPECT_EQ(noErr, GetProcessPID(&shim_psn, &shim_pid));
+ GetFirstAppWindow()->GetBaseWindow()->Close();
+ ASSERT_TRUE(
+ base::WaitForSingleProcess(shim_pid, TestTimeouts::action_timeout()));
+
+ EXPECT_FALSE(GetFirstAppWindow());
+ EXPECT_FALSE(HasAppShimHost(profile(), app->id()));
+ }
+
+ // Case 2: Launch the app, it should start the shim.
+ {
+ base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer;
+ ns_observer.reset([[WindowedNSNotificationObserver alloc]
+ initForNotification:NSWorkspaceDidLaunchApplicationNotification
+ andBundleId:bundle_id]);
+ WindowedAppShimLaunchObserver observer(app->id());
+ LaunchPlatformApp(app);
+ [ns_observer wait];
+ observer.Wait();
+
+ EXPECT_TRUE(GetFirstAppWindow());
+ EXPECT_TRUE(HasAppShimHost(profile(), app->id()));
+
+ // Quitting the shim will eventually cause it to quit. It actually
+ // intercepts the -terminate, sends an AppShimHostMsg_QuitApp to Chrome,
+ // and returns NSTerminateLater. Chrome responds by closing all windows of
+ // the app. Once all windows are closed, Chrome closes the IPC channel,
+ // which causes the shim to actually terminate.
+ NSArray* running_shim = [NSRunningApplication
+ runningApplicationsWithBundleIdentifier:bundle_id];
+ ASSERT_EQ(1u, [running_shim count]);
+
+ ns_observer.reset([[WindowedNSNotificationObserver alloc]
+ initForNotification:NSWorkspaceDidTerminateApplicationNotification
+ andBundleId:bundle_id]);
+ [base::mac::ObjCCastStrict<NSRunningApplication>(
+ [running_shim objectAtIndex:0]) terminate];
+ [ns_observer wait];
+
+ EXPECT_FALSE(GetFirstAppWindow());
+ EXPECT_FALSE(HasAppShimHost(profile(), app->id()));
+ }
+}
+
+} // namespace apps
diff --git a/apps/app_shim/chrome_main_app_mode_mac.mm b/apps/app_shim/chrome_main_app_mode_mac.mm
index 1092142733..18b8f9e1cf 100644
--- a/apps/app_shim/chrome_main_app_mode_mac.mm
+++ b/apps/app_shim/chrome_main_app_mode_mac.mm
@@ -155,7 +155,7 @@ AppShimController::AppShimController()
AppShimController::~AppShimController() {
// Un-set the delegate since NSApplication does not retain it.
- [NSApp setDelegate:nil];
+ [[NSApplication sharedApplication] setDelegate:nil];
}
void AppShimController::OnPingChromeReply(bool success) {
@@ -611,7 +611,11 @@ int ChromeAppModeStart(const app_mode::ChromeAppModeInfo* info) {
main_message_loop.set_thread_name("MainThread");
base::PlatformThread::SetName("CrAppShimMain");
- if (pid == -1) {
+ // In tests, launching Chrome does nothing, and we won't get a ping response,
+ // so just assume the socket exists.
+ if (pid == -1 &&
+ !CommandLine::ForCurrentProcess()->HasSwitch(
+ app_mode::kLaunchedForTest)) {
// Launch Chrome if it isn't already running.
ProcessSerialNumber psn;
CommandLine command_line(CommandLine::NO_PROGRAM);
diff --git a/apps/app_window.cc b/apps/app_window.cc
index dbc28f759a..814d2e0ae8 100644
--- a/apps/app_window.cc
+++ b/apps/app_window.cc
@@ -157,6 +157,8 @@ AppWindow::CreateParams::CreateParams()
: window_type(AppWindow::WINDOW_TYPE_DEFAULT),
frame(AppWindow::FRAME_CHROME),
has_frame_color(false),
+ active_frame_color(SK_ColorBLACK),
+ inactive_frame_color(SK_ColorBLACK),
transparent_background(false),
creator_process_id(0),
state(ui::SHOW_STATE_DEFAULT),
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 2940bce1fa..e2b4e7e712 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -94,7 +94,9 @@
['enable_extensions==0',
{
'sources/': [
- ['exclude', '^apps/'],
+ ['exclude', '.*'],
+ ['include', 'ui/web_contents_sizer\.cc$'],
+ ['include', 'ui/web_contents_sizer\.mm$'],
],
}
],
diff --git a/apps/launcher.cc b/apps/launcher.cc
index 8cfbee970f..72ed7888f1 100644
--- a/apps/launcher.cc
+++ b/apps/launcher.cc
@@ -411,9 +411,9 @@ void LaunchPlatformAppWithCommandLine(Profile* profile,
#if defined(OS_WIN)
base::CommandLine::StringType about_blank_url(
- base::ASCIIToWide(content::kAboutBlankURL));
+ base::ASCIIToWide(url::kAboutBlankURL));
#else
- base::CommandLine::StringType about_blank_url(content::kAboutBlankURL);
+ base::CommandLine::StringType about_blank_url(url::kAboutBlankURL);
#endif
CommandLine::StringVector args = command_line.GetArgs();
// Browser tests will add about:blank to the command line. This should
diff --git a/apps/shell/app/shell_main_delegate.cc b/apps/shell/app/shell_main_delegate.cc
index b8f835d1ae..2a9cd1439f 100644
--- a/apps/shell/app/shell_main_delegate.cc
+++ b/apps/shell/app/shell_main_delegate.cc
@@ -8,6 +8,7 @@
#include "apps/shell/browser/shell_content_browser_client.h"
#include "apps/shell/common/shell_content_client.h"
#include "apps/shell/renderer/shell_content_renderer_client.h"
+#include "apps/shell/renderer/shell_renderer_main_delegate.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
@@ -73,7 +74,8 @@ content::ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() {
content::ContentRendererClient*
ShellMainDelegate::CreateContentRendererClient() {
- renderer_client_.reset(new ShellContentRendererClient);
+ renderer_client_.reset(
+ new ShellContentRendererClient(CreateShellRendererMainDelegate()));
return renderer_client_.get();
}
@@ -81,6 +83,11 @@ ShellBrowserMainDelegate* ShellMainDelegate::CreateShellBrowserMainDelegate() {
return new DefaultShellBrowserMainDelegate();
}
+scoped_ptr<ShellRendererMainDelegate>
+ShellMainDelegate::CreateShellRendererMainDelegate() {
+ return scoped_ptr<ShellRendererMainDelegate>();
+}
+
// static
bool ShellMainDelegate::ProcessNeedsResourceBundle(
const std::string& process_type) {
diff --git a/apps/shell/app/shell_main_delegate.h b/apps/shell/app/shell_main_delegate.h
index 45ba122f32..594f7634da 100644
--- a/apps/shell/app/shell_main_delegate.h
+++ b/apps/shell/app/shell_main_delegate.h
@@ -18,6 +18,7 @@ class ContentRendererClient;
namespace apps {
class ShellBrowserMainDelegate;
+class ShellRendererMainDelegate;
class ShellMainDelegate : public content::ContentMainDelegate {
public:
@@ -35,6 +36,10 @@ class ShellMainDelegate : public content::ContentMainDelegate {
// The created object is owned by ShellBrowserMainParts.
virtual ShellBrowserMainDelegate* CreateShellBrowserMainDelegate();
+ // The returned object is owned by ShellContentRendererClient.
+ virtual scoped_ptr<ShellRendererMainDelegate>
+ CreateShellRendererMainDelegate();
+
private:
// |process_type| is zygote, renderer, utility, etc. Returns true if the
// process needs data from resources.pak.
diff --git a/apps/shell/app_shell.gyp b/apps/shell/app_shell.gyp
index bd5b26a38d..8b2996cf1d 100644
--- a/apps/shell/app_shell.gyp
+++ b/apps/shell/app_shell.gyp
@@ -103,10 +103,13 @@
'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',
@@ -143,6 +146,7 @@
'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', {
diff --git a/apps/shell/browser/default_shell_app_window_controller.cc b/apps/shell/browser/default_shell_app_window_controller.cc
new file mode 100644
index 0000000000..3ec5b6bc84
--- /dev/null
+++ b/apps/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 "apps/shell/browser/default_shell_app_window_controller.h"
+
+#include "apps/shell/browser/shell_app_window.h"
+#include "apps/shell/browser/shell_desktop_controller.h"
+#include "base/logging.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+
+namespace apps {
+
+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 apps
diff --git a/apps/shell/browser/default_shell_app_window_controller.h b/apps/shell/browser/default_shell_app_window_controller.h
new file mode 100644
index 0000000000..36dccd834d
--- /dev/null
+++ b/apps/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 APPS_SHELL_BROWSER_DEFAULT_SHELL_APP_WINDOW_CONTROLLER_H_
+#define APPS_SHELL_BROWSER_DEFAULT_SHELL_APP_WINDOW_CONTROLLER_H_
+
+#include "apps/shell/browser/shell_app_window_controller.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace apps {
+
+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 apps
+
+#endif // APPS_SHELL_BROWSER_DEFAULT_SHELL_APP_WINDOW_CONTROLLER_H_
diff --git a/apps/shell/browser/default_shell_browser_main_delegate.cc b/apps/shell/browser/default_shell_browser_main_delegate.cc
index 3efabbb36d..977c07eed4 100644
--- a/apps/shell/browser/default_shell_browser_main_delegate.cc
+++ b/apps/shell/browser/default_shell_browser_main_delegate.cc
@@ -4,6 +4,7 @@
#include "apps/shell/browser/default_shell_browser_main_delegate.h"
+#include "apps/shell/browser/default_shell_app_window_controller.h"
#include "apps/shell/browser/shell_desktop_controller.h"
#include "apps/shell/browser/shell_extension_system.h"
#include "base/command_line.h"
@@ -29,7 +30,9 @@ void DefaultShellBrowserMainDelegate::Start(
extensions::ShellExtensionSystem* extension_system =
static_cast<extensions::ShellExtensionSystem*>(
extensions::ExtensionSystem::Get(browser_context));
- extension_system->LoadAndLaunchApp(app_absolute_dir);
+ if (!extension_system->LoadApp(app_absolute_dir))
+ return;
+ extension_system->LaunchApp();
} else {
LOG(ERROR) << "--" << kAppSwitch << " unset; boredom is in your future";
}
@@ -40,7 +43,9 @@ void DefaultShellBrowserMainDelegate::Shutdown() {
ShellDesktopController*
DefaultShellBrowserMainDelegate::CreateDesktopController() {
- return new ShellDesktopController();
+ ShellDesktopController* desktop = new ShellDesktopController();
+ desktop->SetAppWindowController(new DefaultShellAppWindowController(desktop));
+ return desktop;
}
} // namespace apps
diff --git a/apps/shell/browser/shell_app_window_controller.h b/apps/shell/browser/shell_app_window_controller.h
new file mode 100644
index 0000000000..13dd982097
--- /dev/null
+++ b/apps/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 APPS_SHELL_BROWSER_SHELL_APP_WINDOW_CONTROLLER_H_
+#define APPS_SHELL_BROWSER_SHELL_APP_WINDOW_CONTROLLER_H_
+
+namespace content {
+class BrowserContext;
+}
+
+namespace apps {
+
+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 apps
+
+#endif // APPS_SHELL_BROWSER_SHELL_APP_WINDOW_CONTROLLER_H_
diff --git a/apps/shell/browser/shell_browser_main_parts.cc b/apps/shell/browser/shell_browser_main_parts.cc
index 3dbfb7c06f..7c1d2938a1 100644
--- a/apps/shell/browser/shell_browser_main_parts.cc
+++ b/apps/shell/browser/shell_browser_main_parts.cc
@@ -19,6 +19,7 @@
#include "extensions/browser/browser_context_keyed_service_factories.h"
#include "extensions/browser/extension_system.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)
@@ -64,6 +65,9 @@ void ShellBrowserMainParts::PostMainMessageLoopStart() {
#if defined(OS_CHROMEOS)
chromeos::DBusThreadManager::Initialize();
network_controller_.reset(new ShellNetworkController);
+#else
+ // Non-Chrome OS platforms are for developer convenience, so use a test IME.
+ ui::InitializeInputMethodForTesting();
#endif
}
diff --git a/apps/shell/browser/shell_desktop_controller.cc b/apps/shell/browser/shell_desktop_controller.cc
index 396758f6dd..2db85b792b 100644
--- a/apps/shell/browser/shell_desktop_controller.cc
+++ b/apps/shell/browser/shell_desktop_controller.cc
@@ -4,7 +4,7 @@
#include "apps/shell/browser/shell_desktop_controller.h"
-#include "apps/shell/browser/shell_app_window.h"
+#include "apps/shell/browser/shell_app_window_controller.h"
#include "content/public/browser/context_factory.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/default_capture_client.h"
@@ -173,8 +173,7 @@ ShellDesktopController::ShellDesktopController() {
}
ShellDesktopController::~ShellDesktopController() {
- // The app window must be explicitly closed before desktop teardown.
- DCHECK(!app_window_);
+ app_window_controller_.reset();
g_instance = NULL;
DestroyRootWindow();
aura::Env::DeleteInstance();
@@ -185,22 +184,20 @@ 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) {
- aura::Window* root_window = 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();
+ return app_window_controller_->CreateAppWindow(context);
}
-void ShellDesktopController::CloseAppWindow() { app_window_.reset(); }
+void ShellDesktopController::CloseAppWindows() {
+ if (app_window_controller_)
+ app_window_controller_->CloseAppWindows();
+}
aura::Window* ShellDesktopController::GetDefaultParent(
aura::Window* context,
@@ -221,7 +218,7 @@ void ShellDesktopController::OnDisplayModeChanged(
void ShellDesktopController::OnHostCloseRequested(
const aura::WindowTreeHost* host) {
DCHECK_EQ(host_.get(), host);
- CloseAppWindow();
+ CloseAppWindows();
base::MessageLoop::current()->PostTask(FROM_HERE,
base::MessageLoop::QuitClosure());
}
@@ -235,7 +232,7 @@ void ShellDesktopController::CreateRootWindow() {
// Set up basic pieces of ui::wm.
gfx::Size size = GetPrimaryDisplaySize();
if (size.IsEmpty())
- size = gfx::Size(800, 600);
+ size = gfx::Size(1366, 768);
host_.reset(aura::WindowTreeHost::Create(gfx::Rect(size)));
host_->InitHost();
diff --git a/apps/shell/browser/shell_desktop_controller.h b/apps/shell/browser/shell_desktop_controller.h
index 2c5b846367..ebededfc59 100644
--- a/apps/shell/browser/shell_desktop_controller.h
+++ b/apps/shell/browser/shell_desktop_controller.h
@@ -49,6 +49,7 @@ class UserActivityDetector;
namespace apps {
class ShellAppWindow;
+class ShellAppWindowController;
// Handles desktop-related tasks for app_shell.
class ShellDesktopController : public aura::client::WindowTreeClient,
@@ -72,12 +73,16 @@ class ShellDesktopController : public aura::client::WindowTreeClient,
// 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 window.
- void CloseAppWindow();
+ // Closes and destroys the app windows.
+ void CloseAppWindows();
// Overridden from aura::client::WindowTreeClient:
virtual aura::Window* GetDefaultParent(aura::Window* context,
@@ -130,7 +135,7 @@ class ShellDesktopController : public aura::client::WindowTreeClient,
#endif
// The desktop supports a single app window.
- scoped_ptr<ShellAppWindow> app_window_;
+ scoped_ptr<ShellAppWindowController> app_window_controller_;
DISALLOW_COPY_AND_ASSIGN(ShellDesktopController);
};
diff --git a/apps/shell/browser/shell_extension_system.cc b/apps/shell/browser/shell_extension_system.cc
index 7d56884fcf..3d2cbc5d34 100644
--- a/apps/shell/browser/shell_extension_system.cc
+++ b/apps/shell/browser/shell_extension_system.cc
@@ -37,21 +37,21 @@ ShellExtensionSystem::ShellExtensionSystem(BrowserContext* browser_context)
ShellExtensionSystem::~ShellExtensionSystem() {
}
-bool ShellExtensionSystem::LoadAndLaunchApp(const base::FilePath& app_dir) {
+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;
- scoped_refptr<Extension> extension = file_util::LoadExtension(
+ extension_ = file_util::LoadExtension(
app_dir, Manifest::COMMAND_LINE, load_flags, &load_error);
- if (!extension) {
+ if (!extension_) {
LOG(ERROR) << "Loading extension at " << app_dir.value()
<< " failed with: " << load_error;
return false;
}
- app_id_ = extension->id();
+ app_id_ = extension_->id();
// TODO(jamescook): We may want to do some of these things here:
// * Create a PermissionsUpdater.
@@ -60,14 +60,14 @@ bool ShellExtensionSystem::LoadAndLaunchApp(const base::FilePath& app_dir) {
// * Call ExtensionPrefs::OnExtensionInstalled().
// * Send NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED.
- ExtensionRegistry::Get(browser_context_)->AddEnabled(extension);
+ ExtensionRegistry::Get(browser_context_)->AddEnabled(extension_);
- RegisterExtensionWithRequestContexts(extension);
+ RegisterExtensionWithRequestContexts(extension_);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
content::Source<BrowserContext>(browser_context_),
- content::Details<const Extension>(extension));
+ content::Details<const Extension>(extension_));
// Inform the rest of the extensions system to start.
ready_.Signal();
@@ -75,11 +75,14 @@ bool ShellExtensionSystem::LoadAndLaunchApp(const base::FilePath& app_dir) {
chrome::NOTIFICATION_EXTENSIONS_READY,
content::Source<BrowserContext>(browser_context_),
content::NotificationService::NoDetails());
+ return true;
+}
+void ShellExtensionSystem::LaunchApp() {
// Send the onLaunched event.
- apps::ShellAPI::DispatchOnLaunchedEvent(event_router_.get(), extension.get());
-
- return true;
+ DCHECK(extension_.get());
+ apps::ShellAPI::DispatchOnLaunchedEvent(event_router_.get(),
+ extension_.get());
}
void ShellExtensionSystem::Shutdown() {
@@ -180,4 +183,10 @@ 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/apps/shell/browser/shell_extension_system.h b/apps/shell/browser/shell_extension_system.h
index a287d2d1fb..c451eddda5 100644
--- a/apps/shell/browser/shell_extension_system.h
+++ b/apps/shell/browser/shell_extension_system.h
@@ -36,13 +36,17 @@ class ShellExtensionSystem : public ExtensionSystem {
explicit ShellExtensionSystem(content::BrowserContext* browser_context);
virtual ~ShellExtensionSystem();
- // Loads an unpacked application from a directory and attempts to launch it.
- // Returns true on success.
- bool LoadAndLaunchApp(const base::FilePath& app_dir);
+ // 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;
@@ -68,6 +72,8 @@ class ShellExtensionSystem : public ExtensionSystem {
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.
@@ -75,6 +81,8 @@ class ShellExtensionSystem : public ExtensionSystem {
// 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_;
diff --git a/apps/shell/browser/shell_network_controller_chromeos.cc b/apps/shell/browser/shell_network_controller_chromeos.cc
index 4280765930..e1bf209fec 100644
--- a/apps/shell/browser/shell_network_controller_chromeos.cc
+++ b/apps/shell/browser/shell_network_controller_chromeos.cc
@@ -125,7 +125,7 @@ void ShellNetworkController::ConnectIfUnconnected() {
return;
chromeos::NetworkStateHandler::NetworkStateList state_list;
- handler->network_state_handler()->GetNetworkListByType(
+ handler->network_state_handler()->GetVisibleNetworkListByType(
chromeos::NetworkTypePattern::WiFi(), &state_list);
for (chromeos::NetworkStateHandler::NetworkStateList::const_iterator it =
state_list.begin(); it != state_list.end(); ++it) {
diff --git a/apps/shell/renderer/shell_content_renderer_client.cc b/apps/shell/renderer/shell_content_renderer_client.cc
index e0217fd2c7..70e0698ce5 100644
--- a/apps/shell/renderer/shell_content_renderer_client.cc
+++ b/apps/shell/renderer/shell_content_renderer_client.cc
@@ -7,6 +7,7 @@
#include "apps/shell/common/shell_extensions_client.h"
#include "apps/shell/renderer/shell_dispatcher_delegate.h"
#include "apps/shell/renderer/shell_extensions_renderer_client.h"
+#include "apps/shell/renderer/shell_renderer_main_delegate.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"
@@ -58,7 +59,10 @@ void ShellFrameHelper::WillReleaseScriptContext(v8::Handle<v8::Context> context,
} // namespace
-ShellContentRendererClient::ShellContentRendererClient() {}
+ShellContentRendererClient::ShellContentRendererClient(
+ scoped_ptr<ShellRendererMainDelegate> delegate)
+ : delegate_(delegate.Pass()) {
+}
ShellContentRendererClient::~ShellContentRendererClient() {}
@@ -80,6 +84,8 @@ void ShellContentRendererClient::RenderThreadStarted() {
// TODO(jamescook): Init WebSecurityPolicy for chrome-extension: schemes.
// See ChromeContentRendererClient for details.
+ if (delegate_)
+ delegate_->OnThreadStarted(thread);
}
void ShellContentRendererClient::RenderFrameCreated(
@@ -91,6 +97,8 @@ void ShellContentRendererClient::RenderFrameCreated(
void ShellContentRendererClient::RenderViewCreated(
content::RenderView* render_view) {
new extensions::ExtensionHelper(render_view, extension_dispatcher_.get());
+ if (delegate_)
+ delegate_->OnViewCreated(render_view);
}
bool ShellContentRendererClient::WillSendRequest(
diff --git a/apps/shell/renderer/shell_content_renderer_client.h b/apps/shell/renderer/shell_content_renderer_client.h
index 506704c693..9f7aee2e22 100644
--- a/apps/shell/renderer/shell_content_renderer_client.h
+++ b/apps/shell/renderer/shell_content_renderer_client.h
@@ -19,11 +19,13 @@ namespace apps {
class ShellExtensionsClient;
class ShellExtensionsRendererClient;
+class ShellRendererMainDelegate;
// Renderer initialization and runtime support for app_shell.
class ShellContentRendererClient : public content::ContentRendererClient {
public:
- ShellContentRendererClient();
+ explicit ShellContentRendererClient(
+ scoped_ptr<ShellRendererMainDelegate> delegate);
virtual ~ShellContentRendererClient();
// content::ContentRendererClient implementation:
@@ -42,6 +44,7 @@ class ShellContentRendererClient : public content::ContentRendererClient {
virtual bool ShouldEnableSiteIsolationPolicy() const OVERRIDE;
private:
+ scoped_ptr<ShellRendererMainDelegate> delegate_;
scoped_ptr<ShellExtensionsClient> extensions_client_;
scoped_ptr<ShellExtensionsRendererClient> extensions_renderer_client_;
scoped_ptr<extensions::DispatcherDelegate> extension_dispatcher_delegate_;
diff --git a/apps/shell/renderer/shell_renderer_main_delegate.h b/apps/shell/renderer/shell_renderer_main_delegate.h
new file mode 100644
index 0000000000..604b6c7288
--- /dev/null
+++ b/apps/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 APPS_SHELL_RENDERER_SHELL_RENDERER_MAIN_DELEGATE_H_
+#define APPS_SHELL_RENDERER_SHELL_RENDERER_MAIN_DELEGATE_H_
+
+namespace content {
+class RenderThread;
+class RenderView;
+}
+
+namespace apps {
+
+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 apps
+
+#endif // APPS_SHELL_RENDERER_SHELL_RENDERER_MAIN_DELEGATE_H_
diff --git a/apps/shell/test/shell_test.cc b/apps/shell/test/shell_test.cc
index 3d2cfeec0d..c5ca5df71a 100644
--- a/apps/shell/test/shell_test.cc
+++ b/apps/shell/test/shell_test.cc
@@ -43,11 +43,14 @@ void AppShellTest::RunTestOnMainThreadLoop() {
TearDownOnMainThread();
// Clean up the app window.
- ShellDesktopController::instance()->CloseAppWindow();
+ ShellDesktopController::instance()->CloseAppWindows();
}
bool AppShellTest::LoadAndLaunchApp(const base::FilePath& app_dir) {
- return extension_system_->LoadAndLaunchApp(app_dir);
+ bool loaded = extension_system_->LoadApp(app_dir);
+ if (loaded)
+ extension_system_->LaunchApp();
+ return loaded;
}
} // namespace apps