| 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 |