1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_apitest.h"
6#include "chrome/browser/extensions/extension_service.h"
7#include "chrome/browser/extensions/extension_test_message_listener.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/browser/ui/browser_list.h"
11#include "chrome/test/ui_test_utils.h"
12
13namespace {
14
15// Find a browser other than |browser|.
16Browser* FindOtherBrowser(Browser* browser) {
17  Browser* found = NULL;
18  for (BrowserList::const_iterator it = BrowserList::begin();
19       it != BrowserList::end(); ++it) {
20    if (*it == browser)
21      continue;
22    found = *it;
23  }
24
25  return found;
26}
27
28}  // namespace
29
30class ExtensionManagementApiTest : public ExtensionApiTest {
31 public:
32  virtual void InstallExtensions() {
33    FilePath basedir = test_data_dir_.AppendASCII("management");
34
35    // Load 4 enabled items.
36    ASSERT_TRUE(LoadExtension(basedir.AppendASCII("enabled_extension")));
37    ASSERT_TRUE(LoadExtension(basedir.AppendASCII("enabled_app")));
38    ASSERT_TRUE(LoadExtension(basedir.AppendASCII("description")));
39    ASSERT_TRUE(LoadExtension(basedir.AppendASCII("permissions")));
40
41    // Load 2 disabled items.
42    ExtensionService* service = browser()->profile()->GetExtensionService();
43    ASSERT_TRUE(LoadExtension(basedir.AppendASCII("disabled_extension")));
44    service->DisableExtension(last_loaded_extension_id_);
45    ASSERT_TRUE(LoadExtension(basedir.AppendASCII("disabled_app")));
46    service->DisableExtension(last_loaded_extension_id_);
47  }
48
49  // Load an app, and wait for a message from app "management/launch_on_install"
50  // indicating that the new app has been launched.
51  void LoadAndWaitForLaunch(const std::string& app_path,
52                            std::string* out_app_id) {
53    ExtensionTestMessageListener launched_app("launched app", false);
54    ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(app_path)));
55
56    if (out_app_id)
57      *out_app_id = last_loaded_extension_id_;
58
59    ASSERT_TRUE(launched_app.WaitUntilSatisfied());
60  }
61};
62
63IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, Basics) {
64  InstallExtensions();
65  ASSERT_TRUE(RunExtensionSubtest("management/test", "basics.html"));
66}
67
68IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, Uninstall) {
69  InstallExtensions();
70  ASSERT_TRUE(RunExtensionSubtest("management/test", "uninstall.html"));
71}
72
73IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, LaunchPanelApp) {
74  ExtensionService* service = browser()->profile()->GetExtensionService();
75
76  // Load an extension that calls launchApp() on any app that gets
77  // installed.
78  ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
79  ASSERT_TRUE(LoadExtension(
80      test_data_dir_.AppendASCII("management/launch_on_install")));
81  ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
82
83  // Load an app with app.launch.container = "panel".
84  std::string app_id;
85  LoadAndWaitForLaunch("management/launch_app_panel", &app_id);
86  ASSERT_FALSE(HasFatalFailure());  // Stop the test if any ASSERT failed.
87
88  // Find the app's browser.  Check that it is a panel.
89  ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
90  Browser* app_browser = FindOtherBrowser(browser());
91  ASSERT_EQ(Browser::TYPE_APP_POPUP, app_browser->type());
92
93  // Close the app panel.
94  app_browser->CloseWindow();
95  ui_test_utils::WaitForNotificationFrom(NotificationType::BROWSER_CLOSED,
96                                           Source<Browser>(app_browser));
97
98  // Unload the extension.
99  UninstallExtension(app_id);
100  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
101  ASSERT_FALSE(service->GetExtensionById(app_id, true));
102
103  // Set a pref indicating that the user wants to launch in a regular tab.
104  // This should be ignored, because panel apps always load in a panel.
105  service->extension_prefs()->SetLaunchType(
106      app_id, ExtensionPrefs::LAUNCH_REGULAR);
107
108  // Load the extension again.
109  std::string app_id_new;
110  LoadAndWaitForLaunch("management/launch_app_panel", &app_id_new);
111  ASSERT_FALSE(HasFatalFailure());
112
113  // If the ID changed, then the pref will not apply to the app.
114  ASSERT_EQ(app_id, app_id_new);
115
116  // Find the app's browser.  Apps that should load in a panel ignore
117  // prefs, so we should still see the launch in a panel.
118  ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
119  app_browser = FindOtherBrowser(browser());
120  ASSERT_EQ(Browser::TYPE_APP_POPUP, app_browser->type());
121}
122
123IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, LaunchTabApp) {
124  ExtensionService* service = browser()->profile()->GetExtensionService();
125
126  // Load an extension that calls launchApp() on any app that gets
127  // installed.
128  ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
129  ASSERT_TRUE(LoadExtension(
130      test_data_dir_.AppendASCII("management/launch_on_install")));
131  ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
132
133  // Code below assumes that the test starts with a single browser window
134  // hosting one tab.
135  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
136  ASSERT_EQ(1, browser()->tab_count());
137
138  // Load an app with app.launch.container = "tab".
139  std::string app_id;
140  LoadAndWaitForLaunch("management/launch_app_tab", &app_id);
141  ASSERT_FALSE(HasFatalFailure());
142
143  // Check that the app opened in a new tab of the existing browser.
144  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
145  ASSERT_EQ(2, browser()->tab_count());
146
147  // Unload the extension.
148  UninstallExtension(app_id);
149  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
150  ASSERT_FALSE(service->GetExtensionById(app_id, true));
151
152  // Set a pref indicating that the user wants to launch in a window.
153  service->extension_prefs()->SetLaunchType(
154      app_id, ExtensionPrefs::LAUNCH_WINDOW);
155
156  std::string app_id_new;
157  LoadAndWaitForLaunch("management/launch_app_tab", &app_id_new);
158  ASSERT_FALSE(HasFatalFailure());
159
160  // If the ID changed, then the pref will not apply to the app.
161  ASSERT_EQ(app_id, app_id_new);
162
163#if defined(OS_MACOSX)
164  // App windows are not yet implemented on mac os.  We should fall back
165  // to a normal tab.
166  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
167  ASSERT_EQ(2, browser()->tab_count());
168#else
169  // Find the app's browser.  Opening in a new window will create
170  // a new browser.
171  ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
172  Browser* app_browser = FindOtherBrowser(browser());
173  ASSERT_EQ(Browser::TYPE_APP, app_browser->type());
174#endif
175}
176