blob: a1675daceb1b8daabbfdac00c77a375e4b2ad592 [file] [log] [blame]
[email protected]a44657202012-01-09 05:48:311// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]cfc6cca2011-12-01 02:30:062// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]a6db6122012-09-03 06:00:235#include "base/bind.h"
[email protected]939532d02012-08-31 23:37:336#include "base/test/test_timeouts.h"
7#include "base/threading/platform_thread.h"
[email protected]b3c019b2012-08-28 02:43:488#include "base/utf_string_conversions.h"
[email protected]ad687a72012-06-08 06:03:119#include "chrome/app/chrome_command_ids.h"
[email protected]605fb8102012-05-04 01:36:5510#include "chrome/browser/automation/automation_util.h"
[email protected]70019152012-12-19 11:44:1911#include "chrome/browser/devtools/devtools_window.h"
[email protected]ddf42162012-11-06 21:14:5512#include "chrome/browser/extensions/api/permissions/permissions_api.h"
[email protected]28c3eeb2012-10-15 05:47:5313#include "chrome/browser/extensions/app_restore_service_factory.h"
14#include "chrome/browser/extensions/app_restore_service.h"
[email protected]a6db6122012-09-03 06:00:2315#include "chrome/browser/extensions/extension_browsertest.h"
[email protected]28c3eeb2012-10-15 05:47:5316#include "chrome/browser/extensions/extension_prefs.h"
17#include "chrome/browser/extensions/extension_service.h"
18#include "chrome/browser/extensions/extension_system.h"
[email protected]259771102012-05-31 16:52:2019#include "chrome/browser/extensions/extension_test_message_listener.h"
20#include "chrome/browser/extensions/platform_app_browsertest_util.h"
[email protected]a6db6122012-09-03 06:00:2321#include "chrome/browser/extensions/platform_app_launcher.h"
[email protected]259771102012-05-31 16:52:2022#include "chrome/browser/extensions/shell_window_registry.h"
[email protected]8c484b742012-11-29 06:05:3623#include "chrome/browser/prefs/pref_service.h"
[email protected]e85cc642012-10-24 06:14:2324#include "chrome/browser/tab_contents/render_view_context_menu.h"
[email protected]cfc6cca2011-12-01 02:30:0625#include "chrome/browser/ui/browser.h"
[email protected]52877dbc62012-06-29 22:22:0326#include "chrome/browser/ui/browser_tabstrip.h"
[email protected]ddf42162012-11-06 21:14:5527#include "chrome/browser/ui/constrained_window_tab_helper.h"
[email protected]a5a0be02012-07-18 05:51:5428#include "chrome/browser/ui/extensions/application_launch.h"
[email protected]1b1989f52012-12-03 08:33:5429#include "chrome/browser/ui/extensions/native_app_window.h"
[email protected]d72d3a62012-05-10 03:45:0830#include "chrome/browser/ui/extensions/shell_window.h"
[email protected]5b1a04b42012-06-15 00:41:4431#include "chrome/common/chrome_notification_types.h"
[email protected]4d007b312012-10-17 03:00:4832#include "chrome/common/url_constants.h"
[email protected]cfc6cca2011-12-01 02:30:0633#include "chrome/test/base/ui_test_utils.h"
[email protected]e85cc642012-10-24 06:14:2334#include "content/public/browser/devtools_agent_host_registry.h"
[email protected]fb29e6cf2012-07-12 21:27:2035#include "content/public/browser/render_process_host.h"
[email protected]a6db6122012-09-03 06:00:2336#include "content/public/browser/web_intents_dispatcher.h"
[email protected]28c3eeb2012-10-15 05:47:5337#include "content/public/test/test_utils.h"
[email protected]a6db6122012-09-03 06:00:2338#include "googleurl/src/gurl.h"
39#include "webkit/glue/web_intent_data.h"
[email protected]cfc6cca2011-12-01 02:30:0640
[email protected]bb81f382012-01-03 22:45:4441using content::WebContents;
[email protected]d9ede582012-08-14 19:21:3842
43namespace extensions {
[email protected]31bdbfef2012-05-22 19:59:1544
[email protected]375003a2011-12-13 02:53:2145namespace {
[email protected]85d3d5e2012-08-31 21:19:1746
[email protected]375003a2011-12-13 02:53:2147// Non-abstract RenderViewContextMenu class.
48class PlatformAppContextMenu : public RenderViewContextMenu {
49 public:
[email protected]bb81f382012-01-03 22:45:4450 PlatformAppContextMenu(WebContents* web_contents,
[email protected]35be7ec2012-02-12 20:42:5151 const content::ContextMenuParams& params)
[email protected]bb81f382012-01-03 22:45:4452 : RenderViewContextMenu(web_contents, params) {}
[email protected]375003a2011-12-13 02:53:2153
[email protected]ad687a72012-06-08 06:03:1154 bool HasCommandWithId(int command_id) {
55 return menu_model_.GetIndexOfCommandId(command_id) != -1;
56 }
57
[email protected]375003a2011-12-13 02:53:2158 protected:
[email protected]85d3d5e2012-08-31 21:19:1759 // RenderViewContextMenu implementation.
60 virtual bool GetAcceleratorForCommandId(
61 int command_id,
62 ui::Accelerator* accelerator) OVERRIDE {
[email protected]375003a2011-12-13 02:53:2163 return false;
64 }
[email protected]85d3d5e2012-08-31 21:19:1765 virtual void PlatformInit() OVERRIDE {}
66 virtual void PlatformCancel() OVERRIDE {}
[email protected]375003a2011-12-13 02:53:2167};
68
[email protected]a6db6122012-09-03 06:00:2369// State holder for the LaunchReply test. This provides an WebIntentsDispatcher
70// that will, when used to launch a Web Intent, will return its reply via this
71// class. The result may then be waited on via WaitUntilReply().
72class LaunchReplyHandler {
73 public:
74 explicit LaunchReplyHandler(webkit_glue::WebIntentData& data)
75 : data_(data),
76 replied_(false),
77 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
78 intents_dispatcher_ = content::WebIntentsDispatcher::Create(data);
79 intents_dispatcher_->RegisterReplyNotification(base::Bind(
80 &LaunchReplyHandler::OnReply, weak_ptr_factory_.GetWeakPtr()));
81 }
82
83 content::WebIntentsDispatcher* intents_dispatcher() {
84 return intents_dispatcher_;
85 }
86
87 // Waits until a reply to this Web Intent is provided via the
88 // WebIntentsDispatcher.
89 bool WaitUntilReply() {
90 if (replied_)
91 return true;
92 waiting_ = true;
93 content::RunMessageLoop();
94 waiting_ = false;
95 return replied_;
96 }
97
98 private:
99 void OnReply(webkit_glue::WebIntentReplyType reply) {
100 // Note that the ReplyNotification registered on WebIntentsDispatcher does
101 // not include the result data: this is reserved for the source page (which
102 // we don't care about).
103 replied_ = true;
104 if (waiting_)
105 MessageLoopForUI::current()->Quit();
106 }
107
108 webkit_glue::WebIntentData data_;
109 bool replied_;
110 bool waiting_;
111 content::WebIntentsDispatcher* intents_dispatcher_;
112 base::WeakPtrFactory<LaunchReplyHandler> weak_ptr_factory_;
113};
114
[email protected]4d007b312012-10-17 03:00:48115// This class keeps track of tabs as they are added to the browser. It will be
116// "done" (i.e. won't block on Wait()) once |observations| tabs have been added.
117class TabsAddedNotificationObserver
118 : public content::WindowedNotificationObserver {
119 public:
120 explicit TabsAddedNotificationObserver(size_t observations)
121 : content::WindowedNotificationObserver(
122 chrome::NOTIFICATION_TAB_ADDED,
123 content::NotificationService::AllSources()),
124 observations_(observations) {
125 }
126
127 virtual void Observe(int type,
128 const content::NotificationSource& source,
129 const content::NotificationDetails& details) OVERRIDE {
130 observed_tabs_.push_back(
131 content::Details<WebContents>(details).ptr());
132 if (observed_tabs_.size() == observations_)
133 content::WindowedNotificationObserver::Observe(type, source, details);
134 }
135
136 const std::vector<content::WebContents*>& tabs() { return observed_tabs_; }
137
138 private:
139 size_t observations_;
140 std::vector<content::WebContents*> observed_tabs_;
141
142 DISALLOW_COPY_AND_ASSIGN(TabsAddedNotificationObserver);
143};
144
[email protected]85d3d5e2012-08-31 21:19:17145const char kTestFilePath[] = "platform_apps/launch_files/test.txt";
146
[email protected]375003a2011-12-13 02:53:21147} // namespace
148
[email protected]eb4bcac2012-06-27 01:32:08149// Tests that CreateShellWindow doesn't crash if you close it straight away.
150// LauncherPlatformAppBrowserTest relies on this behaviour, but is only run for
151// ash, so we test that it works here.
152IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, CreateAndCloseShellWindow) {
153 const Extension* extension = LoadAndLaunchPlatformApp("minimal");
154 ShellWindow* window = CreateShellWindow(extension);
155 CloseShellWindow(window);
156}
157
[email protected]dc37b002012-04-23 23:02:26158// Tests that platform apps received the "launch" event when launched.
159IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OnLaunchedEvent) {
160 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch")) << message_;
[email protected]cfc6cca2011-12-01 02:30:06161}
[email protected]375003a2011-12-13 02:53:21162
[email protected]a6db6122012-09-03 06:00:23163// Tests that platform apps can reply to "launch" events that contain a Web
164// Intent. This test does not test the mechanics of invoking a Web Intent
165// from a source page, and short-circuits to LaunchPlatformAppWithWebIntent.
166IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchReply) {
167 FilePath path = test_data_dir_.AppendASCII("platform_apps/launch_reply");
168 const extensions::Extension* extension = LoadExtension(path);
169 ASSERT_TRUE(extension) << "Failed to load extension.";
170
171 webkit_glue::WebIntentData data(
172 UTF8ToUTF16("http://webintents.org/view"),
173 UTF8ToUTF16("text/plain"),
174 UTF8ToUTF16("irrelevant unserialized string data"));
175 LaunchReplyHandler handler(data);
176
177 // Navigate to a boring page: we don't care what it is, but we require some
178 // source WebContents to launch the Web Intent "from".
179 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
180 WebContents* web_contents = chrome::GetActiveWebContents(browser());
181 ASSERT_TRUE(web_contents);
182
183 extensions::LaunchPlatformAppWithWebIntent(
184 browser()->profile(),
185 extension,
186 handler.intents_dispatcher(),
187 web_contents);
188
189 ASSERT_TRUE(handler.WaitUntilReply());
190}
191
[email protected]567230b2012-08-21 21:11:44192// Tests that platform apps cannot use certain disabled window properties, but
193// can override them and then use them.
194IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) {
195 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties"))
196 << message_;
197}
198
[email protected]edd7ed692012-02-08 02:50:03199IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, EmptyContextMenu) {
[email protected]d9d02762012-12-04 05:18:58200 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]31bdbfef2012-05-22 19:59:15201 LoadAndLaunchPlatformApp("minimal");
[email protected]dc37b002012-04-23 23:02:26202
[email protected]d9d02762012-12-04 05:18:58203 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
204
[email protected]375003a2011-12-13 02:53:21205 // The empty app doesn't add any context menu items, so its menu should
[email protected]0cfacd82012-02-09 01:55:33206 // only include the developer tools.
[email protected]d72d3a62012-05-10 03:45:08207 WebContents* web_contents = GetFirstShellWindowWebContents();
[email protected]a44657202012-01-09 05:48:31208 ASSERT_TRUE(web_contents);
[email protected]375003a2011-12-13 02:53:21209 WebKit::WebContextMenuData data;
[email protected]35be7ec2012-02-12 20:42:51210 content::ContextMenuParams params(data);
[email protected]85d3d5e2012-08-31 21:19:17211 scoped_ptr<PlatformAppContextMenu> menu;
212 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]375003a2011-12-13 02:53:21213 menu->Init();
[email protected]ad687a72012-06-08 06:03:11214 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31215 ASSERT_TRUE(
216 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19217 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]ad687a72012-06-08 06:03:11218 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
219 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
[email protected]375003a2011-12-13 02:53:21220}
221
[email protected]edd7ed692012-02-08 02:50:03222IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenu) {
[email protected]d9d02762012-12-04 05:18:58223 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]375003a2011-12-13 02:53:21224 LoadAndLaunchPlatformApp("context_menu");
225
[email protected]d9d02762012-12-04 05:18:58226 // Wait for the extension to tell us it's initialized its context menus and
227 // launched a window.
228 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
229
[email protected]271d01c2012-08-27 23:48:05230 // The context_menu app has two context menu items. These, along with a
[email protected]0cfacd82012-02-09 01:55:33231 // separator and the developer tools, is all that should be in the menu.
[email protected]d72d3a62012-05-10 03:45:08232 WebContents* web_contents = GetFirstShellWindowWebContents();
[email protected]a44657202012-01-09 05:48:31233 ASSERT_TRUE(web_contents);
[email protected]375003a2011-12-13 02:53:21234 WebKit::WebContextMenuData data;
[email protected]35be7ec2012-02-12 20:42:51235 content::ContextMenuParams params(data);
[email protected]85d3d5e2012-08-31 21:19:17236 scoped_ptr<PlatformAppContextMenu> menu;
237 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]375003a2011-12-13 02:53:21238 menu->Init();
[email protected]ad687a72012-06-08 06:03:11239 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
[email protected]271d01c2012-08-27 23:48:05240 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
[email protected]ad687a72012-06-08 06:03:11241 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31242 ASSERT_TRUE(
243 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19244 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]ad687a72012-06-08 06:03:11245 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
246 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
[email protected]b3c019b2012-08-28 02:43:48247 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
248}
249
[email protected]65992d52012-09-19 23:05:31250IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, InstalledAppWithContextMenu) {
[email protected]d9d02762012-12-04 05:18:58251 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]65992d52012-09-19 23:05:31252 InstallAndLaunchPlatformApp("context_menu");
253
[email protected]d9d02762012-12-04 05:18:58254 // Wait for the extension to tell us it's initialized its context menus and
255 // launched a window.
256 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
257
[email protected]65992d52012-09-19 23:05:31258 // The context_menu app has two context menu items. For an installed app
259 // these are all that should be in the menu.
260 WebContents* web_contents = GetFirstShellWindowWebContents();
261 ASSERT_TRUE(web_contents);
262 WebKit::WebContextMenuData data;
263 content::ContextMenuParams params(data);
264 scoped_ptr<PlatformAppContextMenu> menu;
265 menu.reset(new PlatformAppContextMenu(web_contents, params));
266 menu->Init();
267 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
268 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
269 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
270 ASSERT_FALSE(
271 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19272 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]65992d52012-09-19 23:05:31273 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
274 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
275 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
276}
277
[email protected]b3c019b2012-08-28 02:43:48278IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuTextField) {
[email protected]d9d02762012-12-04 05:18:58279 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]b3c019b2012-08-28 02:43:48280 LoadAndLaunchPlatformApp("context_menu");
281
[email protected]d9d02762012-12-04 05:18:58282 // Wait for the extension to tell us it's initialized its context menus and
283 // launched a window.
284 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
285
[email protected]b3c019b2012-08-28 02:43:48286 // The context_menu app has one context menu item. This, along with a
287 // separator and the developer tools, is all that should be in the menu.
288 WebContents* web_contents = GetFirstShellWindowWebContents();
289 ASSERT_TRUE(web_contents);
290 WebKit::WebContextMenuData data;
291 content::ContextMenuParams params(data);
292 params.is_editable = true;
[email protected]85d3d5e2012-08-31 21:19:17293 scoped_ptr<PlatformAppContextMenu> menu;
294 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]b3c019b2012-08-28 02:43:48295 menu->Init();
296 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
297 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31298 ASSERT_TRUE(
299 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19300 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]b3c019b2012-08-28 02:43:48301 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
302 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
303 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
304 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
305}
306
307IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuSelection) {
[email protected]d9d02762012-12-04 05:18:58308 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]b3c019b2012-08-28 02:43:48309 LoadAndLaunchPlatformApp("context_menu");
310
[email protected]d9d02762012-12-04 05:18:58311 // Wait for the extension to tell us it's initialized its context menus and
312 // launched a window.
313 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
314
[email protected]b3c019b2012-08-28 02:43:48315 // The context_menu app has one context menu item. This, along with a
316 // separator and the developer tools, is all that should be in the menu.
317 WebContents* web_contents = GetFirstShellWindowWebContents();
318 ASSERT_TRUE(web_contents);
319 WebKit::WebContextMenuData data;
320 content::ContextMenuParams params(data);
321 params.selection_text = ASCIIToUTF16("Hello World");
[email protected]85d3d5e2012-08-31 21:19:17322 scoped_ptr<PlatformAppContextMenu> menu;
323 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]b3c019b2012-08-28 02:43:48324 menu->Init();
325 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
326 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31327 ASSERT_TRUE(
328 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19329 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]b3c019b2012-08-28 02:43:48330 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
331 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
332 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
333 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
[email protected]375003a2011-12-13 02:53:21334}
[email protected]5f000f272012-01-19 05:25:08335
[email protected]dc83c582012-08-17 02:18:14336IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuClicked) {
[email protected]d9d02762012-12-04 05:18:58337 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]dc83c582012-08-17 02:18:14338 LoadAndLaunchPlatformApp("context_menu_click");
339
[email protected]d9d02762012-12-04 05:18:58340 // Wait for the extension to tell us it's initialized its context menus and
341 // launched a window.
342 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
343
[email protected]dc83c582012-08-17 02:18:14344 // Test that the menu item shows up
345 WebContents* web_contents = GetFirstShellWindowWebContents();
346 ASSERT_TRUE(web_contents);
347 WebKit::WebContextMenuData data;
348 content::ContextMenuParams params(data);
349 params.page_url = GURL("http://foo.bar");
[email protected]85d3d5e2012-08-31 21:19:17350 scoped_ptr<PlatformAppContextMenu> menu;
351 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]dc83c582012-08-17 02:18:14352 menu->Init();
353 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
354
355 // Execute the menu item
356 ExtensionTestMessageListener onclicked_listener("onClicked fired for id1",
357 false);
358 menu->ExecuteCommand(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST);
359
360 ASSERT_TRUE(onclicked_listener.WaitUntilSatisfied());
361}
362
[email protected]edd7ed692012-02-08 02:50:03363IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowNavigation) {
[email protected]4d007b312012-10-17 03:00:48364 TabsAddedNotificationObserver observer(2);
365
[email protected]dc37b002012-04-23 23:02:26366 ASSERT_TRUE(StartTestServer());
[email protected]d9d02762012-12-04 05:18:58367 ASSERT_TRUE(RunPlatformAppTest("platform_apps/navigation")) << message_;
[email protected]4d007b312012-10-17 03:00:48368
369 observer.Wait();
370 ASSERT_EQ(2U, observer.tabs().size());
371 EXPECT_EQ(std::string(chrome::kExtensionInvalidRequestURL),
372 observer.tabs()[0]->GetURL().spec());
373 EXPECT_EQ("http://chromium.org/",
374 observer.tabs()[1]->GetURL().spec());
[email protected]5f000f272012-01-19 05:25:08375}
[email protected]863e6472012-01-24 19:33:58376
[email protected]40eefd52012-10-04 22:54:22377IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Iframes) {
[email protected]fd3238af2012-05-22 18:55:30378 ASSERT_TRUE(StartTestServer());
379 ASSERT_TRUE(RunPlatformAppTest("platform_apps/iframes")) << message_;
380}
381
[email protected]2aac7ff2012-01-25 18:05:11382// Tests that localStorage and WebSQL are disabled for platform apps.
[email protected]edd7ed692012-02-08 02:50:03383IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) {
[email protected]2aac7ff2012-01-25 18:05:11384 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_;
385}
[email protected]6a5a2e52012-03-22 03:21:12386
[email protected]c0cecd1f2012-04-05 16:50:12387IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Restrictions) {
388 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restrictions")) << message_;
389}
390
[email protected]f0233ff2012-07-20 20:14:50391// Tests that platform apps can use the chrome.app.window.* API.
[email protected]5177f3a2012-11-08 17:51:29392IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, WindowsApi) {
[email protected]6a5a2e52012-03-22 03:21:12393 ASSERT_TRUE(RunPlatformAppTest("platform_apps/windows_api")) << message_;
394}
[email protected]605fb8102012-05-04 01:36:55395
[email protected]1df22042012-08-30 19:48:55396// Tests that extensions can't use platform-app-only APIs.
397IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, PlatformAppsOnly) {
398 ASSERT_TRUE(RunExtensionTestIgnoreManifestWarnings(
399 "platform_apps/apps_only")) << message_;
400}
401
[email protected]605fb8102012-05-04 01:36:55402// Tests that platform apps have isolated storage by default.
403IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Isolation) {
404 ASSERT_TRUE(StartTestServer());
405
406 // Load a (non-app) page under the "localhost" origin that sets a cookie.
407 GURL set_cookie_url = test_server()->GetURL(
408 "files/extensions/platform_apps/isolation/set_cookie.html");
409 GURL::Replacements replace_host;
410 std::string host_str("localhost"); // Must stay in scope with replace_host.
411 replace_host.SetHostStr(host_str);
412 set_cookie_url = set_cookie_url.ReplaceComponents(replace_host);
413
414 ui_test_utils::NavigateToURLWithDisposition(
415 browser(), set_cookie_url,
416 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
417
418 // Make sure the cookie is set.
419 int cookie_size;
420 std::string cookie_value;
421 automation_util::GetCookies(
422 set_cookie_url,
[email protected]52877dbc62012-06-29 22:22:03423 chrome::GetWebContentsAt(browser(), 0),
[email protected]605fb8102012-05-04 01:36:55424 &cookie_size,
425 &cookie_value);
426 ASSERT_EQ("testCookie=1", cookie_value);
427
428 // Let the platform app request the same URL, and make sure that it doesn't
429 // see the cookie.
430 ASSERT_TRUE(RunPlatformAppTest("platform_apps/isolation")) << message_;
431}
[email protected]31bdbfef2012-05-22 19:59:15432
433IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ExtensionWindowingApis) {
434 // Initially there should be just the one browser window visible to the
435 // extensions API.
436 const Extension* extension = LoadExtension(
437 test_data_dir_.AppendASCII("common/background_page"));
438 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
439
440 // And no shell windows.
441 ASSERT_EQ(0U, GetShellWindowCount());
442
443 // Launch a platform app that shows a window.
[email protected]d9d02762012-12-04 05:18:58444 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]ad5bb8a92012-06-07 03:55:58445 LoadAndLaunchPlatformApp("minimal");
[email protected]d9d02762012-12-04 05:18:58446 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
[email protected]31bdbfef2012-05-22 19:59:15447 ASSERT_EQ(1U, GetShellWindowCount());
448 ShellWindowRegistry::ShellWindowSet shell_windows =
449 ShellWindowRegistry::Get(browser()->profile())->shell_windows();
450 int shell_window_id = (*shell_windows.begin())->session_id().id();
451
452 // But it's not visible to the extensions API, it still thinks there's just
453 // one browser window.
454 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
455 // It can't look it up by ID either
456 ASSERT_FALSE(RunGetWindowFunctionForExtension(shell_window_id, extension));
457
458 // The app can also only see one window (its own).
[email protected]ad5bb8a92012-06-07 03:55:58459 // TODO(jeremya): add an extension function to get a shell window by ID, and
460 // to get a list of all the shell windows, so we can test this.
[email protected]31bdbfef2012-05-22 19:59:15461
462 // Launch another platform app that also shows a window.
[email protected]d9d02762012-12-04 05:18:58463 ExtensionTestMessageListener launched_listener2("Launched", false);
[email protected]ad5bb8a92012-06-07 03:55:58464 LoadAndLaunchPlatformApp("context_menu");
[email protected]d9d02762012-12-04 05:18:58465 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
[email protected]31bdbfef2012-05-22 19:59:15466
467 // There are two total shell windows, but each app can only see its own.
468 ASSERT_EQ(2U, GetShellWindowCount());
[email protected]ad5bb8a92012-06-07 03:55:58469 // TODO(jeremya): as above, this requires more extension functions.
[email protected]31bdbfef2012-05-22 19:59:15470}
[email protected]12e540452012-05-26 07:09:36471
[email protected]a2ece522012-10-16 03:41:10472// ChromeOS does not support passing arguments on the command line, so the tests
473// that rely on this functionality are disabled.
[email protected]12e540452012-05-26 07:09:36474#if !defined(OS_CHROMEOS)
475// Tests that command line parameters get passed through to platform apps
476// via launchData correctly when launching with a file.
[email protected]7d0cbb62012-11-22 04:41:07477// TODO(benwells/jeremya): tests need a way to specify a handler ID.
[email protected]12e540452012-05-26 07:09:36478IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFile) {
[email protected]85d3d5e2012-08-31 21:19:17479 SetCommandLineArg(kTestFilePath);
[email protected]12e540452012-05-26 07:09:36480 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file"))
481 << message_;
482}
483
[email protected]a5a0be02012-07-18 05:51:54484// Tests that relative paths can be passed through to the platform app.
485// This test doesn't use the normal test infrastructure as it needs to open
486// the application differently to all other platform app tests, by setting
487// the application_launch::LaunchParams.current_directory field.
488IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithRelativeFile) {
489 // Setup the command line
490 ClearCommandLineArgs();
491 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]85d3d5e2012-08-31 21:19:17492 FilePath relative_test_doc = FilePath::FromUTF8Unsafe(kTestFilePath);
[email protected]a5a0be02012-07-18 05:51:54493 relative_test_doc = relative_test_doc.NormalizePathSeparators();
494 command_line->AppendArgPath(relative_test_doc);
495
496 // Load the extension
497 ResultCatcher catcher;
[email protected]d9ede582012-08-14 19:21:38498 const Extension* extension = LoadExtension(
[email protected]a5a0be02012-07-18 05:51:54499 test_data_dir_.AppendASCII("platform_apps/launch_file"));
500 ASSERT_TRUE(extension);
501
502 // Run the test
503 application_launch::LaunchParams params(browser()->profile(), extension,
504 extension_misc::LAUNCH_NONE,
505 NEW_WINDOW);
506 params.command_line = CommandLine::ForCurrentProcess();
507 params.current_directory = test_data_dir_;
508 application_launch::OpenApplication(params);
509
510 if (!catcher.GetNextResult()) {
511 message_ = catcher.message();
512 ASSERT_TRUE(0);
513 }
514}
515
[email protected]12e540452012-05-26 07:09:36516// Tests that no launch data is sent through if the file is of the wrong MIME
517// type.
518IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongType) {
[email protected]85d3d5e2012-08-31 21:19:17519 SetCommandLineArg(kTestFilePath);
[email protected]12e540452012-05-26 07:09:36520 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_type"))
521 << message_;
522}
523
524// Tests that no launch data is sent through if the platform app does not
525// provide an intent.
526IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNoIntent) {
[email protected]85d3d5e2012-08-31 21:19:17527 SetCommandLineArg(kTestFilePath);
[email protected]12e540452012-05-26 07:09:36528 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_no_intent"))
529 << message_;
530}
531
532// Tests that no launch data is sent through if the file MIME type cannot
533// be read.
534IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoType) {
535 SetCommandLineArg("platform_apps/launch_files/test.unknownextension");
536 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
537 << message_;
538}
539
540// Tests that no launch data is sent through if the file does not exist.
541IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoFile) {
542 SetCommandLineArg("platform_apps/launch_files/doesnotexist.txt");
543 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
544 << message_;
545}
546
547// Tests that no launch data is sent through if the argument is a directory.
548IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithDirectory) {
549 SetCommandLineArg("platform_apps/launch_files");
550 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
551 << message_;
552}
553
554// Tests that no launch data is sent through if there are no arguments passed
555// on the command line
556IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNothing) {
557 ClearCommandLineArgs();
558 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_nothing"))
559 << message_;
560}
[email protected]ffc7b4d2012-06-08 00:05:32561
562// Test that platform apps can use the chrome.fileSystem.getDisplayPath
563// function to get the native file system path of a file they are launched with.
564IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, GetDisplayPath) {
[email protected]85d3d5e2012-08-31 21:19:17565 SetCommandLineArg(kTestFilePath);
[email protected]ffc7b4d2012-06-08 00:05:32566 ASSERT_TRUE(RunPlatformAppTest("platform_apps/get_display_path"))
567 << message_;
568}
569
[email protected]12e540452012-05-26 07:09:36570#endif // defined(OS_CHROMEOS)
[email protected]5b1a04b42012-06-15 00:41:44571
572IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OpenLink) {
573 ASSERT_TRUE(StartTestServer());
[email protected]a7fe9112012-07-20 02:34:45574 content::WindowedNotificationObserver observer(
[email protected]5b1a04b42012-06-15 00:41:44575 chrome::NOTIFICATION_TAB_ADDED,
576 content::Source<content::WebContentsDelegate>(browser()));
577 LoadAndLaunchPlatformApp("open_link");
578 observer.Wait();
579 ASSERT_EQ(2, browser()->tab_count());
580}
[email protected]d9ede582012-08-14 19:21:38581
[email protected]3a8e61942012-08-23 01:46:45582IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MutationEventsDisabled) {
583 ASSERT_TRUE(RunPlatformAppTest("platform_apps/mutation_events")) << message_;
584}
585
[email protected]939532d02012-08-31 23:37:33586// Test that windows created with an id will remember and restore their
587// geometry when opening new windows.
[email protected]69080832012-11-20 20:31:47588// Originally disabled due to flakiness (see http://crbug.com/155459)
589// but now because a regression breaks the test (http://crbug.com/160343).
[email protected]19a0f75d2012-11-29 02:28:31590#if defined(TOOLKIT_GTK)
[email protected]329c4e92012-11-09 06:04:24591#define MAYBE_ShellWindowRestorePosition DISABLED_ShellWindowRestorePosition
[email protected]19a0f75d2012-11-29 02:28:31592#else
593#define MAYBE_ShellWindowRestorePosition ShellWindowRestorePosition
594#endif
[email protected]9d53c1c2012-10-18 00:49:54595IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
[email protected]329c4e92012-11-09 06:04:24596 MAYBE_ShellWindowRestorePosition) {
[email protected]939532d02012-08-31 23:37:33597 ExtensionTestMessageListener page2_listener("WaitForPage2", true);
[email protected]939532d02012-08-31 23:37:33598 ExtensionTestMessageListener done_listener("Done1", false);
599 ExtensionTestMessageListener done2_listener("Done2", false);
[email protected]939532d02012-08-31 23:37:33600
601 ASSERT_TRUE(LoadAndLaunchPlatformApp("geometry"));
602
603 // Wait for the app to be launched (although this is mostly to have a
604 // message to reply to to let the script know it should create its second
605 // window.
606 ASSERT_TRUE(page2_listener.WaitUntilSatisfied());
607
608 // Wait for the first window to verify its geometry was correctly set
609 // from the default* attributes passed to the create function.
610 ASSERT_TRUE(done_listener.WaitUntilSatisfied());
611
612 // Programatically move and resize the window.
613 ShellWindow* window = GetFirstShellWindow();
614 ASSERT_TRUE(window);
615 gfx::Rect bounds(137, 143, 203, 187);
616 window->GetBaseWindow()->SetBounds(bounds);
617
618#if defined(TOOLKIT_GTK)
619 // TODO(mek): On GTK we have to wait for a roundtrip to the X server before
620 // a resize actually happens:
621 // "if you call gtk_window_resize() then immediately call
622 // gtk_window_get_size(), the size won't have taken effect yet. After the
623 // window manager processes the resize request, GTK+ receives notification
624 // that the size has changed via a configure event, and the size of the
625 // window gets updated."
626 // Because of this we have to wait for an unknown time for the resize to
627 // actually take effect. So wait some time or until the resize got
628 // handled.
629 base::TimeTicks end_time = base::TimeTicks::Now() +
630 TestTimeouts::action_timeout();
631 while (base::TimeTicks::Now() < end_time &&
632 bounds != window->GetBaseWindow()->GetBounds()) {
633 content::RunAllPendingInMessageLoop();
634 }
635
636 // In the GTK ShellWindow implementation there also is a delay between
[email protected]99d8f092012-11-28 04:42:43637 // getting the correct bounds and it calling SaveWindowPosition, so call a
[email protected]939532d02012-08-31 23:37:33638 // method explicitly to make sure the value was stored.
[email protected]99d8f092012-11-28 04:42:43639 window->OnNativeWindowChanged();
[email protected]939532d02012-08-31 23:37:33640#endif // defined(TOOLKIT_GTK)
641
642 // Make sure the window was properly moved&resized.
643 ASSERT_EQ(bounds, window->GetBaseWindow()->GetBounds());
644
645 // Tell javascript to open a second window.
646 page2_listener.Reply("continue");
647
648 // Wait for javascript to verify that the second window got the updated
649 // coordinates, ignoring the default coordinates passed to the create method.
650 ASSERT_TRUE(done2_listener.WaitUntilSatisfied());
[email protected]939532d02012-08-31 23:37:33651}
[email protected]939532d02012-08-31 23:37:33652
[email protected]28c3eeb2012-10-15 05:47:53653// Tests that a running app is recorded in the preferences as such.
654IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, RunningAppsAreRecorded) {
655 content::WindowedNotificationObserver extension_suspended(
656 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
657 content::NotificationService::AllSources());
658
659 const Extension* extension = LoadExtension(
660 test_data_dir_.AppendASCII("platform_apps/restart_test"));
661 ASSERT_TRUE(extension);
662 ExtensionService* extension_service =
663 ExtensionSystem::Get(browser()->profile())->extension_service();
664 ExtensionPrefs* extension_prefs = extension_service->extension_prefs();
665
666 // App is running.
667 ASSERT_TRUE(extension_prefs->IsExtensionRunning(extension->id()));
668
669 // Wait for the extension to get suspended.
670 extension_suspended.Wait();
671
672 // App isn't running because it got suspended.
673 ASSERT_FALSE(extension_prefs->IsExtensionRunning(extension->id()));
674
675 // Pretend that the app is supposed to be running.
676 extension_prefs->SetExtensionRunning(extension->id(), true);
677
678 ExtensionTestMessageListener restart_listener("onRestarted", false);
[email protected]119454622012-10-18 09:48:32679 AppRestoreServiceFactory::GetForProfile(browser()->profile())->
680 HandleStartup(true);
[email protected]28c3eeb2012-10-15 05:47:53681 restart_listener.WaitUntilSatisfied();
682}
683
[email protected]545b5312012-11-07 12:18:21684namespace {
685
686class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest {
687 protected:
688 enum TestFlags {
689 RELAUNCH = 0x1,
690 HAS_ID = 0x2,
691 };
692 // Runs a test inside a harness that opens DevTools on a shell window.
693 void RunTestWithDevTools(const char* name, int test_flags);
694};
695
696void PlatformAppDevToolsBrowserTest::RunTestWithDevTools(
697 const char* name, int test_flags) {
[email protected]e85cc642012-10-24 06:14:23698 using content::DevToolsAgentHostRegistry;
[email protected]d9d02762012-12-04 05:18:58699 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]545b5312012-11-07 12:18:21700 const Extension* extension = LoadAndLaunchPlatformApp(name);
[email protected]e85cc642012-10-24 06:14:23701 ASSERT_TRUE(extension);
[email protected]d9d02762012-12-04 05:18:58702 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
[email protected]e85cc642012-10-24 06:14:23703 ShellWindow* window = GetFirstShellWindow();
704 ASSERT_TRUE(window);
[email protected]545b5312012-11-07 12:18:21705 ASSERT_EQ(window->window_key().empty(), (test_flags & HAS_ID) == 0);
[email protected]e85cc642012-10-24 06:14:23706 content::RenderViewHost* rvh = window->web_contents()->GetRenderViewHost();
707 ASSERT_TRUE(rvh);
708
709 // Ensure no DevTools open for the ShellWindow, then open one.
710 ASSERT_FALSE(DevToolsAgentHostRegistry::HasDevToolsAgentHost(rvh));
711 DevToolsWindow* devtools_window = DevToolsWindow::OpenDevToolsWindow(rvh);
712 content::WindowedNotificationObserver loaded_observer(
713 content::NOTIFICATION_LOAD_STOP,
714 content::Source<content::NavigationController>(
[email protected]ee2202a2012-12-11 01:07:20715 &devtools_window->web_contents()->GetController()));
[email protected]e85cc642012-10-24 06:14:23716 loaded_observer.Wait();
717 ASSERT_TRUE(DevToolsAgentHostRegistry::HasDevToolsAgentHost(rvh));
718
[email protected]545b5312012-11-07 12:18:21719 if (test_flags & RELAUNCH) {
720 // Close the ShellWindow, and ensure it is gone.
721 CloseShellWindow(window);
722 ASSERT_FALSE(GetFirstShellWindow());
[email protected]e85cc642012-10-24 06:14:23723
[email protected]545b5312012-11-07 12:18:21724 // Relaunch the app and get a new ShellWindow.
725 content::WindowedNotificationObserver app_loaded_observer(
726 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
727 content::NotificationService::AllSources());
728 application_launch::OpenApplication(application_launch::LaunchParams(
729 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
730 NEW_WINDOW));
731 app_loaded_observer.Wait();
732 window = GetFirstShellWindow();
733 ASSERT_TRUE(window);
[email protected]e85cc642012-10-24 06:14:23734
[email protected]545b5312012-11-07 12:18:21735 // DevTools should have reopened with the relaunch.
736 rvh = window->web_contents()->GetRenderViewHost();
737 ASSERT_TRUE(rvh);
738 ASSERT_TRUE(DevToolsAgentHostRegistry::HasDevToolsAgentHost(rvh));
739 }
[email protected]e85cc642012-10-24 06:14:23740}
741
[email protected]545b5312012-11-07 12:18:21742} // namespace
743
744IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, ReOpenedWithID) {
745 RunTestWithDevTools("minimal_id", RELAUNCH | HAS_ID);
746}
747
748IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, ReOpenedWithURL) {
749 RunTestWithDevTools("minimal", RELAUNCH);
750}
751
[email protected]ddf42162012-11-06 21:14:55752// Test that showing a permission request as a constrained window works and is
753// correctly parented.
754#if defined(OS_MACOSX)
[email protected]cd202662012-11-07 19:11:41755#define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
[email protected]ddf42162012-11-06 21:14:55756#else
757// TODO(sail): Enable this on other platforms once http://crbug.com/95455 is
758// fixed.
759#define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
760#endif
761
762IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ConstrainedWindowRequest) {
763 RequestPermissionsFunction::SetIgnoreUserGestureForTests(true);
764 const Extension* extension =
765 LoadAndLaunchPlatformApp("optional_permission_request");
766 ASSERT_TRUE(extension) << "Failed to load extension.";
767
768 WebContents* web_contents = GetFirstShellWindowWebContents();
769 ASSERT_TRUE(web_contents);
770
771 // Verify that the shell window has a constrained window attached.
772 ConstrainedWindowTabHelper* constrained_window_tab_helper =
773 ConstrainedWindowTabHelper::FromWebContents(web_contents);
774 EXPECT_EQ(1u, constrained_window_tab_helper->constrained_window_count());
775
776 // Close the constrained window and wait for the reply to the permission
777 // request.
778 ExtensionTestMessageListener listener("PermissionRequestDone", false);
779 constrained_window_tab_helper->CloseConstrainedWindows();
780 ASSERT_TRUE(listener.WaitUntilSatisfied());
[email protected]ddf42162012-11-06 21:14:55781}
782
[email protected]bf1be4e2012-11-07 20:32:27783// Tests that an app calling chrome.runtime.reload will reload the app and
784// relaunch it if it was running.
785IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) {
786 ExtensionTestMessageListener launched_listener("Launched", true);
[email protected]d9d02762012-12-04 05:18:58787 const Extension* extension = LoadAndLaunchPlatformApp("reload");
[email protected]bf1be4e2012-11-07 20:32:27788 ASSERT_TRUE(extension);
[email protected]bf1be4e2012-11-07 20:32:27789 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
790 ASSERT_TRUE(GetFirstShellWindow());
791
792 // Now tell the app to reload itself
793 ExtensionTestMessageListener launched_listener2("Launched", false);
794 launched_listener.Reply("reload");
795 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
796 ASSERT_TRUE(GetFirstShellWindow());
[email protected]bf1be4e2012-11-07 20:32:27797}
798
[email protected]8c484b742012-11-29 06:05:36799namespace {
800
801// Simple observer to check for NOTIFICATION_EXTENSION_INSTALLED events to
802// ensure installation does or does not occur in certain scenarios.
803class CheckExtensionInstalledObserver : public content::NotificationObserver {
804 public:
805 CheckExtensionInstalledObserver() : seen_(false) {
806 registrar_.Add(this,
807 chrome::NOTIFICATION_EXTENSION_INSTALLED,
808 content::NotificationService::AllSources());
809 }
810
811 bool seen() const {
812 return seen_;
813 };
814
815 // NotificationObserver:
816 virtual void Observe(int type,
817 const content::NotificationSource& source,
818 const content::NotificationDetails& details) OVERRIDE {
819 EXPECT_FALSE(seen_);
820 seen_ = true;
821 }
822
823 private:
824 bool seen_;
825 content::NotificationRegistrar registrar_;
826};
827
828} // namespace
829
830// Component App Test 1 of 3: ensure that the initial load of a component
831// extension utilizing a background page (e.g. a v2 platform app) has its
832// background page run and is launchable. Waits for the Launched response from
833// the script resource in the opened shell window.
834IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
835 PRE_PRE_ComponentAppBackgroundPage) {
836 CheckExtensionInstalledObserver should_install;
837
838 // Ensure that we wait until the background page is run (to register the
839 // OnLaunched listener) before trying to open the application. This is similar
840 // to LoadAndLaunchPlatformApp, but we want to load as a component extension.
841 content::WindowedNotificationObserver app_loaded_observer(
842 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
843 content::NotificationService::AllSources());
844
845 const Extension* extension = LoadExtensionAsComponent(
846 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
847 ASSERT_TRUE(extension);
848
849 app_loaded_observer.Wait();
850 ASSERT_TRUE(should_install.seen());
851
852 ExtensionTestMessageListener launched_listener("Launched", false);
853 application_launch::OpenApplication(application_launch::LaunchParams(
854 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
855 NEW_WINDOW));
856
857 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
858}
859
860// Component App Test 2 of 3: ensure an installed component app can be launched
861// on a subsequent browser start, without requiring any install/upgrade logic
862// to be run, then perform setup for step 3.
863IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
864 PRE_ComponentAppBackgroundPage) {
865
866 // Since the component app is now installed, re-adding it in the same profile
867 // should not cause it to be re-installed. Instead, we wait for the OnLaunched
868 // in a different observer (which would timeout if not the app was not
869 // previously installed properly) and then check this observer to make sure it
870 // never saw the NOTIFICATION_EXTENSION_INSTALLED event.
871 CheckExtensionInstalledObserver should_not_install;
872 const Extension* extension = LoadExtensionAsComponent(
873 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
874 ASSERT_TRUE(extension);
875
876 ExtensionTestMessageListener launched_listener("Launched", false);
877 application_launch::OpenApplication(application_launch::LaunchParams(
878 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
879 NEW_WINDOW));
880
881 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
882 ASSERT_FALSE(should_not_install.seen());
883
884 // Simulate a "downgrade" from version 2 in the test manifest.json to 1.
885 ExtensionPrefs* extension_prefs =
886 extensions::ExtensionSystem::Get(browser()->profile())->
887 extension_service()->extension_prefs();
888
889 // Clear the registered events to ensure they are updated.
890 extension_prefs->SetRegisteredEvents(extension->id(),
891 std::set<std::string>());
892
893 const base::StringValue old_version("1");
894 std::string pref_path("extensions.settings.");
895 pref_path += extension->id();
896 pref_path += ".manifest.version";
897 extension_prefs->pref_service()->RegisterStringPref(
898 pref_path.c_str(), std::string(), PrefServiceBase::UNSYNCABLE_PREF);
899 extension_prefs->pref_service()->Set(pref_path.c_str(), old_version);
900}
901
902// Component App Test 3 of 3: simulate a component extension upgrade that
903// re-adds the OnLaunched event, and allows the app to be launched.
904IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ComponentAppBackgroundPage) {
905 CheckExtensionInstalledObserver should_install;
906 // Since we are forcing an upgrade, we need to wait for the load again.
907 content::WindowedNotificationObserver app_loaded_observer(
908 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
909 content::NotificationService::AllSources());
910
911 const Extension* extension = LoadExtensionAsComponent(
912 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
913 ASSERT_TRUE(extension);
914 app_loaded_observer.Wait();
915 ASSERT_TRUE(should_install.seen());
916
917 ExtensionTestMessageListener launched_listener("Launched", false);
918 application_launch::OpenApplication(application_launch::LaunchParams(
919 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
920 NEW_WINDOW));
921
922 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
923}
924
[email protected]481a87e62012-12-19 23:00:27925IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Messaging) {
926 ExtensionApiTest::ResultCatcher result_catcher;
927 LoadAndLaunchPlatformApp("messaging/app2");
928 LoadAndLaunchPlatformApp("messaging/app1");
929 EXPECT_TRUE(result_catcher.GetNextResult());
930}
931
[email protected]d9ede582012-08-14 19:21:38932} // namespace extensions