summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authordavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 16:52:20 +0000
committerdavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 16:52:20 +0000
commit259771100a1b9330485f674f58176b04e69720cd (patch)
tree6297c5c179c7f11824712ac165a85356e296ef5d /chrome/browser
parentd5416ff9e1e72b9222ceac6d707b89d3200befb9 (diff)
downloadchromium_src-259771100a1b9330485f674f58176b04e69720cd.zip
chromium_src-259771100a1b9330485f674f58176b04e69720cd.tar.gz
chromium_src-259771100a1b9330485f674f58176b04e69720cd.tar.bz2
Support platform apps in launcher
BUG=125895 TEST=New LauncherPlatformAppBrowserTest.* Review URL: https://chromiumcodereview.appspot.com/10443069 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139805 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/platform_app_browsertest.cc120
-rw-r--r--chrome/browser/extensions/platform_app_browsertest_util.cc123
-rw-r--r--chrome/browser/extensions/platform_app_browsertest_util.h65
-rw-r--r--chrome/browser/extensions/shell_window_registry.cc22
-rw-r--r--chrome/browser/extensions/shell_window_registry.h18
-rw-r--r--chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.cc41
-rw-r--r--chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h9
-rw-r--r--chrome/browser/ui/views/ash/launcher/launcher_platform_app_browsertest.cc126
8 files changed, 404 insertions, 120 deletions
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc
index f21edd9..748090ee 100644
--- a/chrome/browser/extensions/platform_app_browsertest.cc
+++ b/chrome/browser/extensions/platform_app_browsertest.cc
@@ -2,37 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/command_line.h"
-#include "base/stringprintf.h"
-#include "base/string_util.h"
-#include "base/values.h"
#include "chrome/browser/automation/automation_util.h"
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_browsertest.h"
-#include "chrome/browser/extensions/extension_function_test_utils.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/tab_contents/render_view_context_menu.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/platform_app_browsertest_util.h"
#include "chrome/browser/extensions/shell_window_registry.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/render_view_context_menu.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/extensions/shell_window.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_constants.h"
#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/context_menu_params.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/models/menu_model.h"
using content::WebContents;
using extensions::Extension;
-namespace utils = extension_function_test_utils;
-
namespace {
// Non-abstract RenderViewContextMenu class.
class PlatformAppContextMenu : public RenderViewContextMenu {
@@ -54,103 +35,6 @@ class PlatformAppContextMenu : public RenderViewContextMenu {
} // namespace
-class PlatformAppBrowserTest : public ExtensionApiTest {
- public:
- virtual void SetUpCommandLine(CommandLine* command_line) {
- ExtensionBrowserTest::SetUpCommandLine(command_line);
- command_line->AppendSwitch(switches::kEnablePlatformApps);
- command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
- }
-
- protected:
- const Extension* LoadAndLaunchPlatformApp(const char* name) {
- ui_test_utils::WindowedNotificationObserver app_loaded_observer(
- content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
- content::NotificationService::AllSources());
-
- const Extension* extension = LoadExtension(
- test_data_dir_.AppendASCII("platform_apps").AppendASCII(name));
- EXPECT_TRUE(extension);
-
- application_launch::OpenApplication(
- browser()->profile(),
- extension,
- extension_misc::LAUNCH_NONE,
- GURL(),
- NEW_WINDOW,
- NULL);
-
- app_loaded_observer.Wait();
-
- return extension;
- }
-
- // Gets the WebContents associated with the first shell window that is found
- // (most tests only deal with one platform app window, so this is good
- // enough).
- WebContents* GetFirstShellWindowWebContents() {
- ShellWindowRegistry* app_registry =
- ShellWindowRegistry::Get(browser()->profile());
- ShellWindowRegistry::const_iterator iter;
- ShellWindowRegistry::ShellWindowSet shell_windows =
- app_registry->shell_windows();
- for (iter = shell_windows.begin(); iter != shell_windows.end(); ++iter) {
- return (*iter)->web_contents();
- }
-
- return NULL;
- }
-
- // Runs chrome.windows.getAll for the given extension and returns the number
- // of windows that the function returns.
- size_t RunGetWindowsFunctionForExtension(const Extension* extension) {
- GetAllWindowsFunction* function = new GetAllWindowsFunction();
- function->set_extension(extension);
- scoped_ptr<base::ListValue> result(utils::ToList(
- utils::RunFunctionAndReturnResult(function, "[]", browser())));
- return result->GetSize();
- }
-
- // Runs chrome.windows.get(|window_id|) for the the given extension and
- // returns whether or not a window was found.
- bool RunGetWindowFunctionForExtension(
- int window_id, const Extension* extension) {
- GetWindowFunction* function = new GetWindowFunction();
- function->set_extension(extension);
- utils::RunFunction(
- function,
- base::StringPrintf("[%u]", window_id),
- browser(),
- utils::NONE);
- return function->GetResultValue() != NULL;
- }
-
- size_t GetShellWindowCount() {
- return ShellWindowRegistry::Get(browser()->profile())->
- shell_windows().size();
- }
-
- // The command line already has an argument on it - about:blank, which
- // is set by InProcessBrowserTest::PrepareTestCommandLine. For platform app
- // launch tests we need to clear this.
- void ClearCommandLineArgs() {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- CommandLine::StringVector args = command_line->GetArgs();
- CommandLine::StringVector argv = command_line->argv();
- for (size_t i = 0; i < args.size(); i++)
- argv.pop_back();
- command_line->InitFromArgv(argv);
- }
-
- void SetCommandLineArg(const std::string& test_file) {
- ClearCommandLineArgs();
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- FilePath test_doc(test_data_dir_.AppendASCII(test_file));
- test_doc = test_doc.NormalizePathSeparators();
- command_line->AppendArgPath(test_doc);
- }
-};
-
// Tests that platform apps received the "launch" event when launched.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OnLaunchedEvent) {
ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch")) << message_;
diff --git a/chrome/browser/extensions/platform_app_browsertest_util.cc b/chrome/browser/extensions/platform_app_browsertest_util.cc
new file mode 100644
index 0000000..0059e15
--- /dev/null
+++ b/chrome/browser/extensions/platform_app_browsertest_util.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/platform_app_browsertest_util.h"
+#include "base/command_line.h"
+#include "base/stringprintf.h"
+#include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/extensions/shell_window_registry.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/extensions/application_launch.h"
+#include "chrome/browser/ui/extensions/shell_window.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_service.h"
+
+using content::WebContents;
+using extensions::Extension;
+
+namespace utils = extension_function_test_utils;
+
+void PlatformAppBrowserTest::SetUpCommandLine(
+ CommandLine* command_line) {
+ ExtensionBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kEnablePlatformApps);
+ command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
+}
+
+const Extension* PlatformAppBrowserTest::LoadAndLaunchPlatformApp(
+ const char* name) {
+ ui_test_utils::WindowedNotificationObserver app_loaded_observer(
+ content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
+ content::NotificationService::AllSources());
+
+ const Extension* extension = LoadExtension(
+ test_data_dir_.AppendASCII("platform_apps").AppendASCII(name));
+ EXPECT_TRUE(extension);
+
+ application_launch::OpenApplication(
+ browser()->profile(),
+ extension,
+ extension_misc::LAUNCH_NONE,
+ GURL(),
+ NEW_WINDOW,
+ NULL);
+
+ app_loaded_observer.Wait();
+
+ return extension;
+}
+
+WebContents* PlatformAppBrowserTest::GetFirstShellWindowWebContents() {
+ ShellWindowRegistry* app_registry =
+ ShellWindowRegistry::Get(browser()->profile());
+ ShellWindowRegistry::const_iterator iter;
+ ShellWindowRegistry::ShellWindowSet shell_windows =
+ app_registry->shell_windows();
+ for (iter = shell_windows.begin(); iter != shell_windows.end(); ++iter) {
+ return (*iter)->web_contents();
+ }
+
+ return NULL;
+}
+
+size_t PlatformAppBrowserTest::RunGetWindowsFunctionForExtension(
+ const Extension* extension) {
+ GetAllWindowsFunction* function = new GetAllWindowsFunction();
+ function->set_extension(extension);
+ scoped_ptr<base::ListValue> result(utils::ToList(
+ utils::RunFunctionAndReturnResult(function, "[]", browser())));
+ return result->GetSize();
+}
+
+bool PlatformAppBrowserTest::RunGetWindowFunctionForExtension(
+ int window_id,
+ const Extension* extension) {
+ GetWindowFunction* function = new GetWindowFunction();
+ function->set_extension(extension);
+ utils::RunFunction(
+ function,
+ base::StringPrintf("[%u]", window_id),
+ browser(),
+ utils::NONE);
+ return function->GetResultValue() != NULL;
+}
+
+size_t PlatformAppBrowserTest::GetShellWindowCount() {
+ return ShellWindowRegistry::Get(browser()->profile())->
+ shell_windows().size();
+}
+
+void PlatformAppBrowserTest::ClearCommandLineArgs() {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ CommandLine::StringVector args = command_line->GetArgs();
+ CommandLine::StringVector argv = command_line->argv();
+ for (size_t i = 0; i < args.size(); i++)
+ argv.pop_back();
+ command_line->InitFromArgv(argv);
+}
+
+void PlatformAppBrowserTest::SetCommandLineArg(const std::string& test_file) {
+ ClearCommandLineArgs();
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ FilePath test_doc(test_data_dir_.AppendASCII(test_file));
+ test_doc = test_doc.NormalizePathSeparators();
+ command_line->AppendArgPath(test_doc);
+}
+
+ShellWindow* PlatformAppBrowserTest::CreateShellWindow(
+ const Extension* extension) {
+ ShellWindow::CreateParams params;
+ return ShellWindow::Create(
+ browser()->profile(), extension, GURL(""), params);
+}
+
+void PlatformAppBrowserTest::CloseShellWindow(ShellWindow* window) {
+ ui_test_utils::WindowedNotificationObserver destroyed_observer(
+ content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::NotificationService::AllSources());
+ window->Close();
+ destroyed_observer.Wait();
+}
diff --git a/chrome/browser/extensions/platform_app_browsertest_util.h b/chrome/browser/extensions/platform_app_browsertest_util.h
new file mode 100644
index 0000000..b3cfd77
--- /dev/null
+++ b/chrome/browser/extensions/platform_app_browsertest_util.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_PLATFORM_APP_BROWSERTEST_UTIL_H_
+#define CHROME_BROWSER_EXTENSIONS_PLATFORM_APP_BROWSERTEST_UTIL_H_
+#pragma once
+
+
+#include "chrome/browser/extensions/extension_apitest.h"
+
+namespace extensions {
+class Extension;
+}
+
+namespace content {
+class WebContents;
+}
+
+class CommandLine;
+class ShellWindow;
+
+class PlatformAppBrowserTest : public ExtensionApiTest {
+ public:
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
+
+ protected:
+ // Runs the app named |name| out of the platform_apps subdirectory. Waits
+ // until it is launched.
+ const extensions::Extension* LoadAndLaunchPlatformApp(const char* name);
+
+ // Gets the WebContents associated with the first shell window that is found
+ // (most tests only deal with one platform app window, so this is good
+ // enough).
+ content::WebContents* GetFirstShellWindowWebContents();
+
+ // Runs chrome.windows.getAll for the given extension and returns the number
+ // of windows that the function returns.
+ size_t RunGetWindowsFunctionForExtension(
+ const extensions::Extension* extension);
+
+ // Runs chrome.windows.get(|window_id|) for the the given extension and
+ // returns whether or not a window was found.
+ bool RunGetWindowFunctionForExtension(
+ int window_id, const extensions::Extension* extension);
+
+ // Returns the number of shell windows.
+ size_t GetShellWindowCount();
+
+ // The command line already has an argument on it - about:blank, which
+ // is set by InProcessBrowserTest::PrepareTestCommandLine. For platform app
+ // launch tests we need to clear this.
+ void ClearCommandLineArgs();
+
+ // Sets up the command line for running platform apps.
+ void SetCommandLineArg(const std::string& test_file);
+
+ // Creates an empty shell window for |extension|.
+ ShellWindow* CreateShellWindow(const extensions::Extension* extension);
+
+ // Closes |window| and waits until it's gone.
+ void CloseShellWindow(ShellWindow* window);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_PLATFORM_APP_BROWSERTEST_UTIL_H_
diff --git a/chrome/browser/extensions/shell_window_registry.cc b/chrome/browser/extensions/shell_window_registry.cc
index 375fb9c..ab91fe8 100644
--- a/chrome/browser/extensions/shell_window_registry.cc
+++ b/chrome/browser/extensions/shell_window_registry.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/profile_dependency_manager.h"
+#include "chrome/browser/ui/extensions/shell_window.h"
+#include "chrome/common/extensions/extension.h"
ShellWindowRegistry::ShellWindowRegistry() {}
@@ -16,12 +18,32 @@ ShellWindowRegistry* ShellWindowRegistry::Get(Profile* profile) {
void ShellWindowRegistry::AddShellWindow(ShellWindow* shell_window) {
shell_windows_.insert(shell_window);
+ FOR_EACH_OBSERVER(Observer, observers_, OnShellWindowAdded(shell_window));
}
void ShellWindowRegistry::RemoveShellWindow(ShellWindow* shell_window) {
shell_windows_.erase(shell_window);
+ FOR_EACH_OBSERVER(Observer, observers_, OnShellWindowRemoved(shell_window));
}
+void ShellWindowRegistry::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void ShellWindowRegistry::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+ShellWindowRegistry::ShellWindowSet ShellWindowRegistry::GetShellWindowsForApp(
+ const std::string app_id) const {
+ ShellWindowSet app_windows;
+ for (ShellWindowSet::const_iterator i = shell_windows_.begin();
+ i != shell_windows_.end(); ++i) {
+ if ((*i)->extension()->id() == app_id)
+ app_windows.insert(*i);
+ }
+ return app_windows;
+}
///////////////////////////////////////////////////////////////////////////////
// Factory boilerplate
diff --git a/chrome/browser/extensions/shell_window_registry.h b/chrome/browser/extensions/shell_window_registry.h
index a2c5a4e..52b5e18 100644
--- a/chrome/browser/extensions/shell_window_registry.h
+++ b/chrome/browser/extensions/shell_window_registry.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/memory/singleton.h"
+#include "base/observer_list.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h"
@@ -25,6 +26,17 @@ class ShellWindow;
// page).
class ShellWindowRegistry : public ProfileKeyedService {
public:
+ class Observer {
+ public:
+ // Called just after a shell window was added.
+ virtual void OnShellWindowAdded(ShellWindow* shell_window) = 0;
+ // Called just after a shell window was removed.
+ virtual void OnShellWindowRemoved(ShellWindow* shell_window) = 0;
+
+ protected:
+ virtual ~Observer() {}
+ };
+
typedef std::set<ShellWindow*> ShellWindowSet;
typedef ShellWindowSet::const_iterator const_iterator;
@@ -38,6 +50,11 @@ class ShellWindowRegistry : public ProfileKeyedService {
void AddShellWindow(ShellWindow* shell_window);
void RemoveShellWindow(ShellWindow* shell_window);
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Returns a set of windows owned by the application identified by app_id.
+ ShellWindowSet GetShellWindowsForApp(const std::string app_id) const;
const ShellWindowSet& shell_windows() const { return shell_windows_; }
private:
@@ -60,6 +77,7 @@ class ShellWindowRegistry : public ProfileKeyedService {
};
ShellWindowSet shell_windows_;
+ ObserverList<Observer> observers_;
};
#endif // CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
diff --git a/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.cc
index 55f079d..40ce2af 100644
--- a/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.cc
@@ -22,6 +22,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/ash/extension_utils.h"
@@ -68,6 +69,7 @@ ChromeLauncherController::ChromeLauncherController(Profile* profile,
}
instance_ = this;
model_->AddObserver(this);
+ ShellWindowRegistry::Get(profile_)->AddObserver(this);
app_icon_loader_.reset(new LauncherAppIconLoader(profile_, this));
notification_registrar_.Add(this,
@@ -84,6 +86,7 @@ ChromeLauncherController::ChromeLauncherController(Profile* profile,
}
ChromeLauncherController::~ChromeLauncherController() {
+ ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
model_->RemoveObserver(this);
for (IDToItemMap::iterator i = id_to_item_map_.begin();
i != id_to_item_map_.end(); ++i) {
@@ -156,7 +159,10 @@ ash::LauncherID ChromeLauncherController::CreateAppLauncherItem(
ash::LauncherID id = model_->next_id();
ash::LauncherItem item;
if (!controller) {
- item.type = ash::TYPE_APP_SHORTCUT;
+ if (status == ash::STATUS_CLOSED)
+ item.type = ash::TYPE_APP_SHORTCUT;
+ else
+ item.type = ash::TYPE_PLATFORM_APP;
} else if (controller->type() ==
BrowserLauncherItemController::TYPE_APP_PANEL ||
controller->type() ==
@@ -534,6 +540,39 @@ void ChromeLauncherController::Observe(
}
}
+void ChromeLauncherController::OnShellWindowAdded(ShellWindow* shell_window) {
+ const std::string app_id = shell_window->extension()->id();
+ for (IDToItemMap::const_iterator i = id_to_item_map_.begin();
+ i != id_to_item_map_.end(); ++i) {
+ if (i->second.app_id == app_id) {
+ SetItemStatus(i->first, ash::STATUS_RUNNING);
+ return;
+ }
+ }
+ CreateAppLauncherItem(NULL, app_id, ash::STATUS_RUNNING);
+}
+
+void ChromeLauncherController::OnShellWindowRemoved(ShellWindow* shell_window) {
+ const std::string app_id = shell_window->extension()->id();
+ ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile_);
+ if (registry->GetShellWindowsForApp(app_id).size() > 0)
+ return;
+
+ for (IDToItemMap::const_iterator i = id_to_item_map_.begin();
+ i != id_to_item_map_.end(); ++i) {
+ if (i->second.app_id == app_id) {
+ int index = model_->ItemIndexByID(i->first);
+ DCHECK_GE(index, 0);
+ ash::LauncherItem item = model_->items()[index];
+ if (item.type == ash::TYPE_APP_SHORTCUT)
+ SetItemStatus(i->first, ash::STATUS_CLOSED);
+ else
+ LauncherItemClosed(i->first);
+ return;
+ }
+ }
+}
+
void ChromeLauncherController::PersistPinnedState() {
// It is a coding error to call PersistPinnedState() if the pinned apps are
// not user-editable. The code should check earlier and not perform any
diff --git a/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h
index 1bdc5f6..df67e5a4 100644
--- a/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h
+++ b/chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h
@@ -19,6 +19,7 @@
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/extensions/shell_window_registry.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -36,7 +37,8 @@ class TabContentsWrapper;
// browsers (BrowserLauncherItemController) and browser shortcuts.
class ChromeLauncherController : public ash::LauncherDelegate,
public ash::LauncherModelObserver,
- public content::NotificationObserver {
+ public content::NotificationObserver,
+ public ShellWindowRegistry::Observer {
public:
// Indicates if a launcher item is incognito or not.
enum IncognitoState {
@@ -180,6 +182,11 @@ class ChromeLauncherController : public ash::LauncherDelegate,
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
+
+ // Overridden from ShellWindowRegistry::Observer:
+ virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE;
+ virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE;
+
private:
friend class BrowserLauncherItemControllerTest;
diff --git a/chrome/browser/ui/views/ash/launcher/launcher_platform_app_browsertest.cc b/chrome/browser/ui/views/ash/launcher/launcher_platform_app_browsertest.cc
new file mode 100644
index 0000000..af586f8
--- /dev/null
+++ b/chrome/browser/ui/views/ash/launcher/launcher_platform_app_browsertest.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/launcher/launcher.h"
+#include "ash/launcher/launcher_model.h"
+#include "ash/shell.h"
+#include "base/command_line.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/automation/automation_util.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/platform_app_browsertest_util.h"
+#include "chrome/browser/extensions/shell_window_registry.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/render_view_context_menu.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/extensions/application_launch.h"
+#include "chrome/browser/ui/extensions/shell_window.h"
+#include "chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/context_menu_params.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/models/menu_model.h"
+
+using extensions::Extension;
+
+typedef PlatformAppBrowserTest LauncherPlatformAppBrowserTest;
+
+// Test that we can launch a platform app and get a running item.
+IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) {
+ ash::Launcher* launcher = ash::Shell::GetInstance()->launcher();
+ int item_count = launcher->model()->item_count();
+ const Extension* extension = LoadAndLaunchPlatformApp("launch");
+ ShellWindow* window = CreateShellWindow(extension);
+ ++item_count;
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+ ash::LauncherItem item =
+ launcher->model()->items()[launcher->model()->item_count() - 2];
+ ASSERT_EQ(ash::TYPE_PLATFORM_APP, item.type);
+ ASSERT_EQ(ash::STATUS_RUNNING, item.status);
+ CloseShellWindow(window);
+ --item_count;
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+}
+
+// Test that we can launch a platform app that already has a shortcut.
+IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) {
+ ash::Launcher* launcher = ash::Shell::GetInstance()->launcher();
+ int item_count = launcher->model()->item_count();
+
+ // First get app_id.
+ const Extension* extension = LoadAndLaunchPlatformApp("launch");
+ const std::string app_id = extension->id();
+
+ // Then create a shortcut.
+ ChromeLauncherController* controller =
+ static_cast<ChromeLauncherController*>(launcher->delegate());
+ ash::LauncherID shortcut_id =
+ controller->CreateAppLauncherItem(NULL, app_id, ash::STATUS_CLOSED);
+ ++item_count;
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+ ash::LauncherItem item = *launcher->model()->ItemByID(shortcut_id);
+ ASSERT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
+ ASSERT_EQ(ash::STATUS_CLOSED, item.status);
+
+ // Open a window. Confirm the item is now running.
+ ShellWindow* window = CreateShellWindow(extension);
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+ item = *launcher->model()->ItemByID(shortcut_id);
+ ASSERT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
+ ASSERT_EQ(ash::STATUS_RUNNING, item.status);
+
+ // Then close it, make sure there's still an item.
+ CloseShellWindow(window);
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+ item = *launcher->model()->ItemByID(shortcut_id);
+ ASSERT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
+ ASSERT_EQ(ash::STATUS_CLOSED, item.status);
+}
+
+// Test that we can launch a platform app with more than one window.
+IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) {
+ ash::Launcher* launcher = ash::Shell::GetInstance()->launcher();
+ int item_count = launcher->model()->item_count();
+
+ // First run app.
+ const Extension* extension = LoadAndLaunchPlatformApp("launch");
+ ShellWindow* window1 = CreateShellWindow(extension);
+ ++item_count;
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+ ash::LauncherItem item =
+ launcher->model()->items()[launcher->model()->item_count() - 2];
+ ash::LauncherID item_id = item.id;
+ ASSERT_EQ(ash::TYPE_PLATFORM_APP, item.type);
+ ASSERT_EQ(ash::STATUS_RUNNING, item.status);
+
+ // Add second window.
+ ShellWindow* window2 = CreateShellWindow(extension);
+ // Confirm item stays.
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+ item = *launcher->model()->ItemByID(item_id);
+ ASSERT_EQ(ash::STATUS_RUNNING, item.status);
+
+ // Close second window.
+ CloseShellWindow(window2);
+ // Confirm item stays.
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+ item = *launcher->model()->ItemByID(item_id);
+ ASSERT_EQ(ash::STATUS_RUNNING, item.status);
+
+ // Close first window.
+ CloseShellWindow(window1);
+ // Confirm item is removed.
+ --item_count;
+ ASSERT_EQ(item_count, launcher->model()->item_count());
+}