OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 <algorithm> | |
6 #include <iterator> | |
7 | |
8 #include "base/bind.h" | |
9 #include "base/callback.h" | |
10 #include "base/command_line.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/string_util.h" | |
13 #include "base/stringprintf.h" | |
14 #include "base/threading/sequenced_worker_pool.h" | |
15 #include "base/utf_string_conversions.h" | |
16 #include "chrome/browser/favicon/favicon_service.h" | |
17 #include "chrome/browser/favicon/favicon_service_factory.h" | |
18 #include "chrome/browser/intents/default_web_intent_service.h" | |
19 #include "chrome/browser/profiles/profile.h" | |
20 #include "chrome/browser/ui/browser.h" | |
21 #include "chrome/browser/ui/browser_commands.h" | |
22 #include "chrome/browser/ui/intents/web_intent_picker.h" | |
23 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | |
24 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | |
25 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" | |
26 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
27 #include "chrome/browser/webdata/web_data_service.h" | |
28 #include "chrome/browser/webdata/web_data_service_factory.h" | |
29 #include "chrome/common/chrome_notification_types.h" | |
30 #include "chrome/common/chrome_switches.h" | |
31 #include "chrome/common/url_constants.h" | |
32 #include "chrome/test/base/in_process_browser_test.h" | |
33 #include "chrome/test/base/ui_test_utils.h" | |
34 #include "content/public/browser/browser_thread.h" | |
35 #include "content/public/browser/notification_service.h" | |
36 #include "content/public/browser/web_contents.h" | |
37 #include "content/public/browser/web_intents_dispatcher.h" | |
38 #include "content/public/test/test_utils.h" | |
39 #include "extensions/common/constants.h" | |
40 #include "net/base/escape.h" | |
41 #include "net/base/mock_host_resolver.h" | |
42 #include "net/url_request/test_url_fetcher_factory.h" | |
43 #include "testing/gtest/include/gtest/gtest.h" | |
44 #include "ui/gfx/image/image_unittest_util.h" | |
45 #include "ui/gfx/image/image_util.h" | |
46 #include "webkit/glue/web_intent_service_data.h" | |
47 | |
48 namespace { | |
49 | |
50 const string16 kAction1(ASCIIToUTF16("http://webintents.org/share")); | |
51 const string16 kAction2(ASCIIToUTF16("http://www.example.com/foobar")); | |
52 const string16 kType1(ASCIIToUTF16("image/png")); | |
53 const string16 kType2(ASCIIToUTF16("text/*")); | |
54 const GURL kServiceURL1("http://www.google.com"); | |
55 const GURL kServiceURL2("http://www.chromium.org"); | |
56 const char kDummyExtensionId[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; | |
57 const char kCWSResponseEmpty[] = | |
58 "{\"kind\":\"chromewebstore#itemList\",\"total_items\":0,\"start_index\":0," | |
59 "\"items\":[]}"; | |
60 | |
61 const char kCWSResponseResultFormat[] = | |
62 "{\"kind\":\"chromewebstore#itemList\"," | |
63 "\"total_items\":1," | |
64 "\"start_index\":0," | |
65 "\"items\":[{" | |
66 "\"kind\":\"chromewebstore#item\"," | |
67 "\"id\":\"%s\"," | |
68 "\"type\":\"APPLICATION\"," | |
69 "\"num_ratings\":0," | |
70 "\"average_rating\":0.0," | |
71 "\"manifest\": \"{\\n" | |
72 "\\\"name\\\": \\\"Dummy Share\\\",\\n" | |
73 "\\\"version\\\": \\\"1.0.0.0\\\",\\n" | |
74 "\\\"intents\\\": {\\n" | |
75 "\\\"%s\\\" : {\\n" | |
76 "\\\"type\\\" : [\\\"%s\\\"],\\n" | |
77 "\\\"path\\\" : \\\"share.html\\\",\\n" | |
78 "\\\"title\\\" : \\\"Dummy share!\\\",\\n" | |
79 "\\\"disposition\\\": \\\"inline\\\"\\n" | |
80 "}\\n" | |
81 "}\\n" | |
82 "}\\n\"," | |
83 "\"family_safe\":true," | |
84 "\"icon_url\": \"%s\"}]}"; | |
85 | |
86 const char kCWSFakeIconURLFormat[] = "http://example.com/%s/icon.png"; | |
87 | |
88 class DummyURLFetcherFactory : public net::URLFetcherFactory { | |
89 public: | |
90 DummyURLFetcherFactory() {} | |
91 virtual ~DummyURLFetcherFactory() {} | |
92 | |
93 virtual net::URLFetcher* CreateURLFetcher( | |
94 int id, | |
95 const GURL& url, | |
96 net::URLFetcher::RequestType request_type, | |
97 net::URLFetcherDelegate* d) OVERRIDE { | |
98 return new net::TestURLFetcher(id, url, d); | |
99 } | |
100 }; | |
101 | |
102 } // namespace | |
103 | |
104 class WebIntentPickerMock : public WebIntentPicker, | |
105 public WebIntentPickerModelObserver { | |
106 public: | |
107 WebIntentPickerMock() | |
108 : num_installed_services_(0), | |
109 num_icons_changed_(0), | |
110 num_extension_icons_changed_(0), | |
111 num_extensions_installed_(0), | |
112 message_loop_started_(false), | |
113 pending_async_completed_(false), | |
114 num_inline_disposition_(0), | |
115 delegate_(NULL) { | |
116 } | |
117 | |
118 void MockClose() { | |
119 delegate_->OnClosing(); | |
120 } | |
121 | |
122 // WebIntentPicker implementation. | |
123 virtual void Close() OVERRIDE { StopWaiting(); } | |
124 virtual void SetActionString(const string16& action) OVERRIDE {} | |
125 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE { | |
126 num_extensions_installed_++; | |
127 } | |
128 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE {} | |
129 virtual void OnInlineDispositionAutoResize(const gfx::Size& size) OVERRIDE {} | |
130 virtual void OnPendingAsyncCompleted() OVERRIDE { | |
131 StopWaiting(); | |
132 } | |
133 virtual void InvalidateDelegate() OVERRIDE { | |
134 delegate_ = NULL; | |
135 } | |
136 | |
137 // WebIntentPickerModelObserver implementation. | |
138 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE { | |
139 num_installed_services_ = | |
140 static_cast<int>(model->GetInstalledServiceCount()); | |
141 } | |
142 virtual void OnFaviconChanged( | |
143 WebIntentPickerModel* model, size_t index) OVERRIDE { | |
144 num_icons_changed_++; | |
145 } | |
146 virtual void OnExtensionIconChanged( | |
147 WebIntentPickerModel* model, const std::string& extension_id) OVERRIDE { | |
148 num_extension_icons_changed_++; | |
149 } | |
150 virtual void OnInlineDisposition( | |
151 const string16& title, const GURL& url) OVERRIDE { | |
152 num_inline_disposition_++; | |
153 } | |
154 | |
155 void Wait() { | |
156 if (!pending_async_completed_) { | |
157 message_loop_started_ = true; | |
158 content::RunMessageLoop(); | |
159 pending_async_completed_ = false; | |
160 } | |
161 } | |
162 | |
163 void StopWaiting() { | |
164 pending_async_completed_ = true; | |
165 if (message_loop_started_) { | |
166 message_loop_started_ = false; | |
167 MessageLoop::current()->Quit(); | |
168 } | |
169 } | |
170 | |
171 int num_installed_services_; | |
172 int num_icons_changed_; | |
173 int num_extension_icons_changed_; | |
174 int num_extensions_installed_; | |
175 bool message_loop_started_; | |
176 bool pending_async_completed_; | |
177 int num_inline_disposition_; | |
178 WebIntentPickerDelegate* delegate_; | |
179 }; | |
180 | |
181 class IntentsDispatcherMock : public content::WebIntentsDispatcher { | |
182 public: | |
183 explicit IntentsDispatcherMock(const webkit_glue::WebIntentData& intent) | |
184 : intent_(intent), | |
185 dispatched_(false), | |
186 replied_(false) {} | |
187 | |
188 virtual const webkit_glue::WebIntentData& GetIntent() OVERRIDE { | |
189 return intent_; | |
190 } | |
191 | |
192 virtual void DispatchIntent(content::WebContents* web_contents) OVERRIDE { | |
193 dispatched_ = true; | |
194 } | |
195 | |
196 virtual void ResetDispatch() OVERRIDE { | |
197 } | |
198 | |
199 virtual void SendReply(const webkit_glue::WebIntentReply& reply) OVERRIDE { | |
200 replied_ = true; | |
201 } | |
202 | |
203 virtual void RegisterReplyNotification( | |
204 const base::Callback<void(webkit_glue::WebIntentReplyType)>&) OVERRIDE { | |
205 } | |
206 | |
207 webkit_glue::WebIntentData intent_; | |
208 bool dispatched_; | |
209 bool replied_; | |
210 }; | |
211 | |
212 class WebIntentPickerControllerBrowserTest : public InProcessBrowserTest { | |
213 public: | |
214 WebIntentPickerControllerBrowserTest() {} | |
215 | |
216 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
217 // We start the test server now instead of in | |
218 // SetUpInProcessBrowserTestFixture so that we can get its port number. | |
219 ASSERT_TRUE(test_server()->Start()); | |
220 | |
221 net::HostPortPair host_port = test_server()->host_port_pair(); | |
222 command_line->AppendSwitchASCII( | |
223 switches::kAppsGalleryDownloadURL, | |
224 base::StringPrintf( | |
225 "http://www.example.com:%d/files/extensions/intents/%%s.crx", | |
226 host_port.port())); | |
227 command_line->AppendSwitchASCII( | |
228 switches::kAppsGalleryInstallAutoConfirmForTests, "accept"); | |
229 } | |
230 | |
231 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { | |
232 host_resolver()->AddRule("www.example.com", "127.0.0.1"); | |
233 } | |
234 | |
235 content::WebContents* GetWindowDispositionTarget( | |
236 WebIntentPickerController* controller) { | |
237 return controller->window_disposition_source_; | |
238 } | |
239 | |
240 virtual void SetUpOnMainThread() OVERRIDE { | |
241 // The FakeURLFetcherFactory will return a NULL URLFetcher if a request is | |
242 // created for a URL it doesn't know and there is no default factory. | |
243 // Instead, use this dummy factory to infinitely delay the request. | |
244 default_url_fetcher_factory_.reset(new DummyURLFetcherFactory); | |
245 fake_url_fetcher_factory_.reset( | |
246 new net::FakeURLFetcherFactory(default_url_fetcher_factory_.get())); | |
247 | |
248 web_data_service_ = WebDataServiceFactory::GetForProfile( | |
249 GetBrowser()->profile(), Profile::EXPLICIT_ACCESS); | |
250 favicon_service_ = FaviconServiceFactory::GetForProfile( | |
251 GetBrowser()->profile(), Profile::EXPLICIT_ACCESS); | |
252 controller_ = WebIntentPickerController::FromWebContents( | |
253 GetBrowser()->tab_strip_model()->GetActiveWebContents()); | |
254 | |
255 SetupMockPicker(); | |
256 controller_->set_model_observer(&picker_); | |
257 picker_.delegate_ = controller_; | |
258 | |
259 CreateFakeIcon(); | |
260 } | |
261 | |
262 virtual void SetupMockPicker() { | |
263 controller_->set_picker(&picker_); | |
264 } | |
265 | |
266 virtual Browser* GetBrowser() { return browser(); } | |
267 | |
268 void AddWebIntentService(const string16& action, const GURL& service_url) { | |
269 webkit_glue::WebIntentServiceData service; | |
270 service.action = action; | |
271 service.type = kType1; | |
272 service.service_url = service_url; | |
273 web_data_service_->AddWebIntentService(service); | |
274 } | |
275 | |
276 void AddCWSExtensionServiceEmpty(const string16& action) { | |
277 GURL cws_query_url = CWSIntentsRegistry::BuildQueryURL(action, kType1); | |
278 fake_url_fetcher_factory_->SetFakeResponse(cws_query_url.spec(), | |
279 kCWSResponseEmpty, true); | |
280 } | |
281 | |
282 void AddCWSExtensionServiceWithResult(const std::string& extension_id, | |
283 const string16& action, | |
284 const string16& type) { | |
285 GURL cws_query_url = CWSIntentsRegistry::BuildQueryURL(action, type); | |
286 std::string icon_url; | |
287 std::string escaped_action = net::EscapePath(UTF16ToUTF8(action)); | |
288 base::SStringPrintf(&icon_url, kCWSFakeIconURLFormat, | |
289 escaped_action.c_str()); | |
290 | |
291 std::string response; | |
292 base::SStringPrintf(&response, kCWSResponseResultFormat, | |
293 extension_id.c_str(), | |
294 UTF16ToUTF8(action).c_str(), UTF16ToUTF8(type).c_str(), | |
295 icon_url.c_str()); | |
296 fake_url_fetcher_factory_->SetFakeResponse(cws_query_url.spec(), response, | |
297 true); | |
298 | |
299 fake_url_fetcher_factory_->SetFakeResponse(icon_url, icon_response_, | |
300 true); | |
301 } | |
302 | |
303 void SetDefaultService(const string16& action, | |
304 const std::string& url) { | |
305 DefaultWebIntentService default_service; | |
306 default_service.action = action; | |
307 default_service.type = kType1; | |
308 default_service.user_date = 1000000; | |
309 default_service.service_url = url; | |
310 web_data_service_->AddDefaultWebIntentService(default_service); | |
311 } | |
312 | |
313 void OnSendReturnMessage( | |
314 webkit_glue::WebIntentReplyType reply_type) { | |
315 controller_->OnSendReturnMessage(reply_type); | |
316 } | |
317 | |
318 void OnServiceChosen( | |
319 const GURL& url, | |
320 webkit_glue::WebIntentServiceData::Disposition disposition) { | |
321 controller_->OnServiceChosen(url, disposition, | |
322 WebIntentPickerDelegate::kEnableDefaults); | |
323 } | |
324 | |
325 void OnCancelled() { | |
326 controller_->OnUserCancelledPickerDialog(); | |
327 } | |
328 | |
329 void OnExtensionInstallRequested(const std::string& extension_id) { | |
330 controller_->OnExtensionInstallRequested(extension_id); | |
331 } | |
332 | |
333 extensions::WebstoreInstaller* GetWebstoreInstaller() const { | |
334 return controller_->webstore_installer_.get(); | |
335 } | |
336 | |
337 void CreateFakeIcon() { | |
338 gfx::Image image(gfx::test::CreateImage()); | |
339 scoped_refptr<base::RefCountedMemory> image_data = image.As1xPNGBytes(); | |
340 DCHECK(image_data->size()); | |
341 | |
342 std::copy(image_data->front(), image_data->front() + image_data->size(), | |
343 std::back_inserter(icon_response_)); | |
344 } | |
345 | |
346 void ClickLocationBarButton(content::WebContents* service_web_contents) { | |
347 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
348 WebIntentPickerController* service_controller = | |
349 WebIntentPickerController::FromWebContents(service_web_contents); | |
350 service_controller->LocationBarPickerButtonClicked(); | |
351 } | |
352 | |
353 void CloseCurrentTab() { | |
354 content::WindowedNotificationObserver tab_close_observer( | |
355 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
356 content::NotificationService::AllSources()); | |
357 chrome::CloseTab(browser()); | |
358 tab_close_observer.Wait(); | |
359 } | |
360 | |
361 WebIntentPickerMock picker_; | |
362 scoped_refptr<WebDataService> web_data_service_; | |
363 FaviconService* favicon_service_; | |
364 WebIntentPickerController* controller_; | |
365 scoped_ptr<DummyURLFetcherFactory> default_url_fetcher_factory_; | |
366 scoped_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_; | |
367 std::string icon_response_; | |
368 }; | |
369 | |
370 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, ChooseService) { | |
371 AddWebIntentService(kAction1, kServiceURL1); | |
372 AddWebIntentService(kAction1, kServiceURL2); | |
373 AddCWSExtensionServiceEmpty(kAction1); | |
374 | |
375 webkit_glue::WebIntentData intent; | |
376 intent.action = kAction1; | |
377 intent.type = kType1; | |
378 IntentsDispatcherMock dispatcher(intent); | |
379 controller_->SetIntentsDispatcher(&dispatcher); | |
380 | |
381 controller_->ShowDialog(kAction1, kType1); | |
382 picker_.Wait(); | |
383 EXPECT_EQ(2, picker_.num_installed_services_); | |
384 EXPECT_EQ(0, picker_.num_icons_changed_); | |
385 | |
386 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
387 OnServiceChosen(kServiceURL2, | |
388 webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW); | |
389 ASSERT_EQ(2, tab_strip->count()); | |
390 EXPECT_EQ(GURL(kServiceURL2), | |
391 tab_strip->GetActiveWebContents()->GetURL()); | |
392 | |
393 EXPECT_TRUE(GetWindowDispositionTarget( | |
394 WebIntentPickerController::FromWebContents( | |
395 tab_strip->GetActiveWebContents()))); | |
396 | |
397 EXPECT_TRUE(dispatcher.dispatched_); | |
398 | |
399 OnSendReturnMessage(webkit_glue::WEB_INTENT_REPLY_SUCCESS); | |
400 ASSERT_EQ(1, tab_strip->count()); | |
401 } | |
402 | |
403 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
404 FetchExtensionIcon) { | |
405 AddWebIntentService(kAction1, kServiceURL1); | |
406 AddWebIntentService(kAction1, kServiceURL2); | |
407 AddCWSExtensionServiceWithResult(kDummyExtensionId, kAction1, kType1); | |
408 | |
409 webkit_glue::WebIntentData intent; | |
410 intent.action = kAction1; | |
411 intent.type = kType1; | |
412 IntentsDispatcherMock dispatcher(intent); | |
413 controller_->SetIntentsDispatcher(&dispatcher); | |
414 | |
415 controller_->ShowDialog(kAction1, kType1); | |
416 picker_.Wait(); | |
417 // Flush all pending worker tasks for PNG decoding. | |
418 content::BrowserThread::GetBlockingPool()->FlushForTesting(); | |
419 // Flush all tasks posted from the worker tasks. | |
420 MessageLoop::current()->RunUntilIdle(); | |
421 EXPECT_EQ(2, picker_.num_installed_services_); | |
422 EXPECT_EQ(0, picker_.num_icons_changed_); | |
423 EXPECT_EQ(1, picker_.num_extension_icons_changed_); | |
424 } | |
425 | |
426 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, OpenCancelOpen) { | |
427 AddWebIntentService(kAction1, kServiceURL1); | |
428 AddWebIntentService(kAction1, kServiceURL2); | |
429 AddCWSExtensionServiceEmpty(kAction1); | |
430 | |
431 webkit_glue::WebIntentData intent; | |
432 intent.action = kAction1; | |
433 intent.type = kType1; | |
434 IntentsDispatcherMock dispatcher(intent); | |
435 controller_->SetIntentsDispatcher(&dispatcher); | |
436 | |
437 controller_->ShowDialog(kAction1, kType1); | |
438 picker_.Wait(); | |
439 OnCancelled(); | |
440 | |
441 controller_->ShowDialog(kAction1, kType1); | |
442 OnCancelled(); | |
443 } | |
444 | |
445 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
446 CloseTargetTabReturnToSource) { | |
447 AddWebIntentService(kAction1, kServiceURL1); | |
448 AddCWSExtensionServiceEmpty(kAction1); | |
449 | |
450 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
451 GURL original = tab_strip->GetActiveWebContents()->GetURL(); | |
452 | |
453 // Open a new page, but keep focus on original. | |
454 ui_test_utils::NavigateToURLWithDisposition( | |
455 browser(), GURL(chrome::kChromeUINewTabURL), NEW_BACKGROUND_TAB, | |
456 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
457 ASSERT_EQ(2, tab_strip->count()); | |
458 EXPECT_EQ(original, tab_strip->GetActiveWebContents()->GetURL()); | |
459 | |
460 webkit_glue::WebIntentData intent; | |
461 intent.action = kAction1; | |
462 intent.type = kType1; | |
463 IntentsDispatcherMock dispatcher(intent); | |
464 controller_->SetIntentsDispatcher(&dispatcher); | |
465 | |
466 controller_->ShowDialog(kAction1, kType1); | |
467 picker_.Wait(); | |
468 EXPECT_EQ(1, picker_.num_installed_services_); | |
469 | |
470 OnServiceChosen(kServiceURL1, | |
471 webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW); | |
472 ASSERT_EQ(3, tab_strip->count()); | |
473 EXPECT_EQ(GURL(kServiceURL1), | |
474 tab_strip->GetActiveWebContents()->GetURL()); | |
475 | |
476 EXPECT_TRUE(dispatcher.dispatched_); | |
477 | |
478 OnSendReturnMessage(webkit_glue::WEB_INTENT_REPLY_SUCCESS); | |
479 ASSERT_EQ(2, tab_strip->count()); | |
480 EXPECT_EQ(original, tab_strip->GetActiveWebContents()->GetURL()); | |
481 | |
482 CloseCurrentTab(); | |
483 } | |
484 | |
485 class WebIntentPickerControllerIncognitoBrowserTest | |
486 : public WebIntentPickerControllerBrowserTest { | |
487 public: | |
488 WebIntentPickerControllerIncognitoBrowserTest() {} | |
489 | |
490 virtual void SetUpOnMainThread() OVERRIDE { | |
491 incognito_browser_ = CreateIncognitoBrowser(); | |
492 WebIntentPickerControllerBrowserTest::SetUpOnMainThread(); | |
493 } | |
494 | |
495 virtual Browser* GetBrowser() OVERRIDE { return incognito_browser_; } | |
496 | |
497 int pending_async_count() { return controller_->pending_async_count_; } | |
498 | |
499 private: | |
500 Browser* incognito_browser_; | |
501 }; | |
502 | |
503 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerIncognitoBrowserTest, | |
504 ShowDialogShouldntCrash) { | |
505 webkit_glue::WebIntentData intent; | |
506 intent.action = kAction1; | |
507 intent.type = kType1; | |
508 IntentsDispatcherMock dispatcher(intent); | |
509 controller_->SetIntentsDispatcher(&dispatcher); | |
510 | |
511 controller_->ShowDialog(kAction1, kType1); | |
512 // This should do nothing for now. | |
513 EXPECT_EQ(0, pending_async_count()); | |
514 } | |
515 | |
516 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
517 ExtensionInstallSuccess) { | |
518 const char extension_id[] = "ooodacpbmglpoagccnepcbfhfhpdgddn"; | |
519 AddCWSExtensionServiceWithResult(extension_id, kAction1, kType2); | |
520 | |
521 webkit_glue::WebIntentData intent; | |
522 intent.action = kAction1; | |
523 intent.type = kType2; | |
524 IntentsDispatcherMock dispatcher(intent); | |
525 controller_->SetIntentsDispatcher(&dispatcher); | |
526 | |
527 controller_->ShowDialog(kAction1, kType2); | |
528 picker_.Wait(); | |
529 | |
530 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
531 ASSERT_EQ(1, tab_strip->count()); | |
532 OnExtensionInstallRequested(extension_id); | |
533 picker_.Wait(); | |
534 EXPECT_EQ(1, picker_.num_extensions_installed_); | |
535 const extensions::Extension* extension = browser()->profile()-> | |
536 GetExtensionService()->GetExtensionById(extension_id, false); | |
537 EXPECT_TRUE(extension); | |
538 | |
539 // Installing an extension should also choose it. Since this extension uses | |
540 // window disposition, it will create a new tab. | |
541 EXPECT_EQ(2, tab_strip->count()); | |
542 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
543 | |
544 CloseCurrentTab(); | |
545 } | |
546 | |
547 // Tests that inline install of an extension using inline disposition works | |
548 // and brings up content as inline content. | |
549 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
550 ExtensionInstallSuccessInline) { | |
551 const char extension_id[] = "nnhendkbgefomfgdlnmfhhmihihlljpi"; | |
552 AddCWSExtensionServiceWithResult(extension_id, kAction1, kType2); | |
553 | |
554 webkit_glue::WebIntentData intent; | |
555 intent.action = kAction1; | |
556 intent.type = kType2; | |
557 IntentsDispatcherMock dispatcher(intent); | |
558 controller_->SetIntentsDispatcher(&dispatcher); | |
559 | |
560 controller_->ShowDialog(kAction1, kType2); | |
561 picker_.Wait(); | |
562 | |
563 OnExtensionInstallRequested(extension_id); | |
564 picker_.Wait(); | |
565 EXPECT_EQ(1, picker_.num_extensions_installed_); | |
566 const extensions::Extension* extension = browser()->profile()-> | |
567 GetExtensionService()->GetExtensionById(extension_id, false); | |
568 EXPECT_TRUE(extension); | |
569 | |
570 // Installing an extension should also choose it. Since this extension uses | |
571 // inline disposition, it will create no tabs and invoke OnInlineDisposition. | |
572 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
573 EXPECT_EQ(1, tab_strip->count()); | |
574 EXPECT_EQ(1, picker_.num_inline_disposition_); | |
575 } | |
576 | |
577 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
578 WebstoreInstallerLifetime) { | |
579 const char extension_id[] = "nnhendkbgefomfgdlnmfhhmihihlljpi"; | |
580 AddCWSExtensionServiceWithResult(extension_id, kAction1, kType2); | |
581 | |
582 webkit_glue::WebIntentData intent; | |
583 intent.action = kAction1; | |
584 intent.type = kType2; | |
585 IntentsDispatcherMock dispatcher(intent); | |
586 controller_->SetIntentsDispatcher(&dispatcher); | |
587 | |
588 controller_->ShowDialog(kAction1, kType2); | |
589 picker_.Wait(); | |
590 | |
591 // We haven't yet created a WebstoreInstaller. | |
592 EXPECT_FALSE(GetWebstoreInstaller()); | |
593 | |
594 // While extension install is pending, we have a WebstoreInstaller. | |
595 OnExtensionInstallRequested(extension_id); | |
596 EXPECT_TRUE(GetWebstoreInstaller()); | |
597 | |
598 // After extension install the WebstoreInstaller is cleaned up. | |
599 picker_.Wait(); | |
600 EXPECT_EQ(1, picker_.num_extensions_installed_); | |
601 EXPECT_FALSE(GetWebstoreInstaller()); | |
602 } | |
603 | |
604 // Test that an explicit intent does not trigger loading intents from the | |
605 // registry (skips the picker), and creates the intent service handler | |
606 // immediately. | |
607 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
608 ExplicitIntentTest) { | |
609 // Install a target service for the explicit intent. | |
610 const char extension_id[] = "ooodacpbmglpoagccnepcbfhfhpdgddn"; | |
611 AddCWSExtensionServiceWithResult(extension_id, kAction1, kType2); | |
612 | |
613 webkit_glue::WebIntentData intent; | |
614 intent.action = kAction1; | |
615 intent.type = kType2; | |
616 IntentsDispatcherMock dispatcher(intent); | |
617 controller_->SetIntentsDispatcher(&dispatcher); | |
618 | |
619 controller_->ShowDialog(kAction1, kType2); | |
620 picker_.Wait(); | |
621 | |
622 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
623 OnExtensionInstallRequested(extension_id); | |
624 picker_.Wait(); | |
625 ASSERT_EQ(1, picker_.num_extensions_installed_); | |
626 // The intent launches a new tab. | |
627 ASSERT_EQ(2, tab_strip->count()); | |
628 | |
629 // Make the controller think nothing is being shown. | |
630 picker_.MockClose(); | |
631 SetupMockPicker(); | |
632 | |
633 // Now call the explicit intent. | |
634 webkit_glue::WebIntentData explicitIntent; | |
635 explicitIntent.action = kAction1; | |
636 explicitIntent.type = kType2; | |
637 explicitIntent.service = GURL(StringPrintf("%s://%s/%s", | |
638 extensions::kExtensionScheme, | |
639 extension_id, | |
640 "share.html")); | |
641 IntentsDispatcherMock dispatcher2(explicitIntent); | |
642 controller_->SetIntentsDispatcher(&dispatcher2); | |
643 ui_test_utils::WindowedTabAddedNotificationObserver new_tab_observer(( | |
644 content::Source<content::WebContentsDelegate>(browser()))); | |
645 controller_->ShowDialog(kAction1, kType2); | |
646 new_tab_observer.Wait(); | |
647 | |
648 content::WebContents* service_web_contents = new_tab_observer.GetTab(); | |
649 DCHECK(service_web_contents); | |
650 | |
651 // Location bar button should not be shown for explicit intents. | |
652 WebIntentPickerController* service_controller = | |
653 WebIntentPickerController::FromWebContents(service_web_contents); | |
654 DCHECK(service_controller); | |
655 EXPECT_FALSE(service_controller->ShowLocationBarPickerButton()); | |
656 | |
657 EXPECT_EQ(3, tab_strip->count()); | |
658 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
659 EXPECT_FALSE(dispatcher2.replied_); | |
660 | |
661 // num_installed_services_ would be 2 if the intent wasn't explicit. | |
662 EXPECT_EQ(1, picker_.num_installed_services_); | |
663 | |
664 // Close tabs to get rid of them before the dispatchers go out of scope at the | |
665 // end of this method. | |
666 CloseCurrentTab(); | |
667 CloseCurrentTab(); | |
668 } | |
669 | |
670 // Test that an explicit intent for non-installed extension won't | |
671 // complete. | |
672 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
673 ExplicitIntentNoExtensionTest) { | |
674 AddWebIntentService(kAction1, kServiceURL1); | |
675 AddWebIntentService(kAction1, kServiceURL2); | |
676 AddCWSExtensionServiceWithResult(kDummyExtensionId, kAction1, kType1); | |
677 | |
678 webkit_glue::WebIntentData intent; | |
679 intent.action = kAction1; | |
680 intent.type = kType1; | |
681 intent.service = GURL(StringPrintf("%s://%s/%s", | |
682 extensions::kExtensionScheme, | |
683 kDummyExtensionId, | |
684 UTF16ToASCII(kAction1).c_str())); | |
685 IntentsDispatcherMock dispatcher(intent); | |
686 controller_->SetIntentsDispatcher(&dispatcher); | |
687 controller_->ShowDialog(kAction1, kType1); | |
688 picker_.Wait(); | |
689 | |
690 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
691 EXPECT_EQ(1, tab_strip->count()); | |
692 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
693 EXPECT_TRUE(dispatcher.replied_); | |
694 | |
695 // num_installed_services_ would be 2 if the intent wasn't explicit. | |
696 EXPECT_EQ(0, picker_.num_installed_services_); | |
697 } | |
698 | |
699 // Test that explicit intents won't load uninstalled non-extensions. | |
700 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
701 ExplicitIntentNonExtensionTest) { | |
702 AddWebIntentService(kAction1, kServiceURL1); | |
703 AddWebIntentService(kAction1, kServiceURL2); | |
704 AddCWSExtensionServiceWithResult(kDummyExtensionId, kAction1, kType1); | |
705 | |
706 webkit_glue::WebIntentData intent; | |
707 intent.action = kAction1; | |
708 intent.type = kType1; | |
709 intent.service = GURL("http://www.uninstalled.com/"); | |
710 IntentsDispatcherMock dispatcher(intent); | |
711 controller_->SetIntentsDispatcher(&dispatcher); | |
712 controller_->ShowDialog(kAction1, kType1); | |
713 picker_.Wait(); | |
714 | |
715 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
716 EXPECT_EQ(1, tab_strip->count()); | |
717 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
718 | |
719 // num_installed_services_ would be 2 if the intent wasn't explicit. | |
720 EXPECT_EQ(0, picker_.num_installed_services_); | |
721 EXPECT_TRUE(dispatcher.replied_); | |
722 } | |
723 | |
724 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
725 DefaultsTest) { | |
726 AddWebIntentService(kAction1, kServiceURL1); | |
727 AddWebIntentService(kAction1, kServiceURL2); | |
728 AddCWSExtensionServiceEmpty(kAction1); | |
729 | |
730 SetDefaultService(kAction1, kServiceURL1.spec()); | |
731 | |
732 webkit_glue::WebIntentData intent; | |
733 intent.action = kAction1; | |
734 intent.type = kType1; | |
735 IntentsDispatcherMock dispatcher(intent); | |
736 controller_->SetIntentsDispatcher(&dispatcher); | |
737 | |
738 ui_test_utils::WindowedTabAddedNotificationObserver new_tab_observer(( | |
739 content::Source<content::WebContentsDelegate>(browser()))); | |
740 controller_->ShowDialog(kAction1, kType1); | |
741 new_tab_observer.Wait(); | |
742 WebIntentPickerController* service_controller = | |
743 WebIntentPickerController::FromWebContents(new_tab_observer.GetTab()); | |
744 EXPECT_TRUE(service_controller->ShowLocationBarPickerButton()); | |
745 | |
746 EXPECT_EQ(2, picker_.num_installed_services_); | |
747 | |
748 // The tab is shown immediately without needing to call OnServiceChosen. | |
749 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
750 ASSERT_EQ(2, tab_strip->count()); | |
751 EXPECT_EQ(GURL(kServiceURL1), | |
752 tab_strip->GetActiveWebContents()->GetURL()); | |
753 | |
754 EXPECT_TRUE(dispatcher.dispatched_); | |
755 | |
756 CloseCurrentTab(); | |
757 } | |
758 | |
759 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
760 ChooseAnotherService) { | |
761 AddWebIntentService(kAction1, kServiceURL1); | |
762 AddWebIntentService(kAction1, kServiceURL2); | |
763 AddCWSExtensionServiceEmpty(kAction1); | |
764 | |
765 // Bring up the picker to get the test-installed services so we can create a | |
766 // default with the right defaulting fingerprint. | |
767 SetDefaultService(kAction1, kServiceURL1.spec()); | |
768 | |
769 webkit_glue::WebIntentData intent; | |
770 intent.action = kAction1; | |
771 intent.type = kType1; | |
772 IntentsDispatcherMock dispatcher(intent); | |
773 controller_->SetIntentsDispatcher(&dispatcher); | |
774 | |
775 ui_test_utils::WindowedTabAddedNotificationObserver new_tab_observer(( | |
776 content::Source<content::WebContentsDelegate>(browser()))); | |
777 controller_->ShowDialog(kAction1, kType1); | |
778 new_tab_observer.Wait(); | |
779 content::WebContents* service_web_contents = new_tab_observer.GetTab(); | |
780 | |
781 EXPECT_EQ(2, picker_.num_installed_services_); | |
782 | |
783 // The tab is shown immediately without needing to call OnServiceChosen. | |
784 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
785 ASSERT_EQ(2, tab_strip->count()); | |
786 EXPECT_EQ(GURL(kServiceURL1), | |
787 tab_strip->GetActiveWebContents()->GetURL()); | |
788 | |
789 // Simulate click on the location bar use-another-service button. | |
790 content::WindowedNotificationObserver observer( | |
791 chrome::NOTIFICATION_TAB_CLOSING, | |
792 content::NotificationService::AllSources()); | |
793 content::BrowserThread::PostTask( | |
794 content::BrowserThread::UI, FROM_HERE, | |
795 base::Bind(&WebIntentPickerControllerBrowserTest::ClickLocationBarButton, | |
796 base::Unretained(this), | |
797 service_web_contents)); | |
798 observer.Wait(); | |
799 picker_.Wait(); | |
800 | |
801 // The service tab is closed and the picker is shown again | |
802 // on the original tab. | |
803 EXPECT_EQ(1, tab_strip->count()); | |
804 EXPECT_EQ(2, picker_.num_installed_services_); | |
805 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
806 } | |
OLD | NEW |