- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / streams_private / streams_private_apitest.cc
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 "base/command_line.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/prefs/pref_service.h"
8 #include "chrome/browser/download/download_prefs.h"
9 #include "chrome/browser/extensions/event_router.h"
10 #include "chrome/browser/extensions/extension_apitest.h"
11 #include "chrome/browser/extensions/extension_info_map.h"
12 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/common/extensions/mime_types_handler.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/test/base/test_switches.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/download_item.h"
21 #include "content/public/browser/download_manager.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/resource_controller.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/test/download_test_observer.h"
26 #include "net/test/embedded_test_server/embedded_test_server.h"
27 #include "net/test/embedded_test_server/http_request.h"
28 #include "net/test/embedded_test_server/http_response.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30
31 using content::BrowserContext;
32 using content::BrowserThread;
33 using content::DownloadItem;
34 using content::DownloadManager;
35 using content::DownloadUrlParameters;
36 using content::ResourceController;
37 using content::WebContents;
38 using extensions::Event;
39 using extensions::ExtensionSystem;
40 using net::test_server::BasicHttpResponse;
41 using net::test_server::HttpRequest;
42 using net::test_server::HttpResponse;
43 using net::test_server::EmbeddedTestServer;
44 using testing::_;
45
46 namespace {
47
48 // Test server's request handler.
49 // Returns response that should be sent by the test server.
50 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
51   scoped_ptr<BasicHttpResponse> response(new BasicHttpResponse());
52
53   // For relative path "/doc_path.doc", return success response with MIME type
54   // "application/msword".
55   if (request.relative_url == "/doc_path.doc") {
56     response->set_code(net::HTTP_OK);
57     response->set_content_type("application/msword");
58     return response.PassAs<HttpResponse>();
59   }
60
61   // For relative path "/test_path_attch.txt", return success response with
62   // MIME type "plain/text" and content "txt content". Also, set content
63   // disposition to be attachment.
64   if (request.relative_url == "/text_path_attch.txt") {
65     response->set_code(net::HTTP_OK);
66     response->set_content("txt content");
67     response->set_content_type("plain/text");
68     response->AddCustomHeader("Content-Disposition",
69                               "attachment; filename=test_path.txt");
70     return response.PassAs<HttpResponse>();
71   }
72   // For relative path "/test_path_attch.txt", return success response with
73   // MIME type "plain/text" and content "txt content".
74   if (request.relative_url == "/text_path.txt") {
75     response->set_code(net::HTTP_OK);
76     response->set_content("txt content");
77     response->set_content_type("plain/text");
78     return response.PassAs<HttpResponse>();
79   }
80
81   // No other requests should be handled in the tests.
82   EXPECT_TRUE(false) << "NOTREACHED!";
83   response->set_code(net::HTTP_NOT_FOUND);
84   return response.PassAs<HttpResponse>();
85 }
86
87 // Tests to verify that resources are correctly intercepted by
88 // StreamsResourceThrottle.
89 // The test extension expects the resources that should be handed to the
90 // extension to have MIME type 'application/msword' and the resources that
91 // should be downloaded by the browser to have MIME type 'plain/text'.
92 class StreamsPrivateApiTest : public ExtensionApiTest {
93  public:
94   StreamsPrivateApiTest() {}
95
96   virtual ~StreamsPrivateApiTest() {}
97
98   virtual void SetUpOnMainThread() OVERRIDE {
99     // Init test server.
100     test_server_.reset(new EmbeddedTestServer);
101     ASSERT_TRUE(test_server_->InitializeAndWaitUntilReady());
102     test_server_->RegisterRequestHandler(base::Bind(&HandleRequest));
103
104     ExtensionApiTest::SetUpOnMainThread();
105   }
106
107   virtual void CleanUpOnMainThread() OVERRIDE {
108     // Tear down the test server.
109     EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete());
110     test_server_.reset();
111     ExtensionApiTest::CleanUpOnMainThread();
112   }
113
114   void InitializeDownloadSettings() {
115     ASSERT_TRUE(browser());
116     ASSERT_TRUE(downloads_dir_.CreateUniqueTempDir());
117
118     // Setup default downloads directory to the scoped tmp directory created for
119     // the test.
120     browser()->profile()->GetPrefs()->SetFilePath(
121         prefs::kDownloadDefaultDirectory, downloads_dir_.path());
122     // Ensure there are no prompts for download during the test.
123     browser()->profile()->GetPrefs()->SetBoolean(
124         prefs::kPromptForDownload, false);
125
126     DownloadManager* manager = GetDownloadManager();
127     DownloadPrefs::FromDownloadManager(manager)->ResetAutoOpen();
128     manager->RemoveAllDownloads();
129   }
130
131   // Sends onExecuteContentHandler event with the MIME type "test/done" to the
132   // test extension.
133   // The test extension calls 'chrome.test.notifySuccess' when it receives the
134   // event with the "test/done" MIME type (unless the 'chrome.test.notifyFail'
135   // has already been called).
136   void SendDoneEvent() {
137     scoped_ptr<base::ListValue> event_args(new base::ListValue());
138     event_args->Append(new base::StringValue("test/done"));
139     event_args->Append(new base::StringValue("http://foo"));
140     event_args->Append(new base::StringValue("blob://bar"));
141     event_args->Append(new base::FundamentalValue(10));
142     event_args->Append(new base::FundamentalValue(20));
143
144     scoped_ptr<Event> event(new Event(
145         "streamsPrivate.onExecuteMimeTypeHandler", event_args.Pass()));
146
147     ExtensionSystem::Get(browser()->profile())->event_router()->
148         DispatchEventToExtension(test_extension_id_, event.Pass());
149   }
150
151   // Loads the test extension and set's up its file_browser_handler to handle
152   // 'application/msword' and 'plain/text' MIME types.
153   // The extension will notify success when it detects an event with the MIME
154   // type 'application/msword' and notify fail when it detects an event with the
155   // MIME type 'plain/text'.
156   const extensions::Extension* LoadTestExtension() {
157     // The test extension id is set by the key value in the manifest.
158     test_extension_id_ = "oickdpebdnfbgkcaoklfcdhjniefkcji";
159
160     const extensions::Extension* extension = LoadExtension(
161         test_data_dir_.AppendASCII("streams_private/handle_mime_type"));
162     if (!extension)
163       return NULL;
164
165     MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
166     if (!handler) {
167       message_ = "No mime type handlers defined.";
168       return NULL;
169     }
170
171     DCHECK_EQ(test_extension_id_, extension->id());
172
173     return extension;
174   }
175
176   // Returns the download manager for the current browser.
177   DownloadManager* GetDownloadManager() const {
178     DownloadManager* download_manager =
179         BrowserContext::GetDownloadManager(browser()->profile());
180     EXPECT_TRUE(download_manager);
181     return download_manager;
182   }
183
184   // Deletes the download and waits until it's flushed.
185   // The |manager| should have |download| in its list of downloads.
186   void DeleteDownloadAndWaitForFlush(DownloadItem* download,
187                                      DownloadManager* manager) {
188     scoped_refptr<content::DownloadTestFlushObserver> flush_observer(
189         new content::DownloadTestFlushObserver(manager));
190     download->Remove();
191     flush_observer->WaitForFlush();
192   }
193
194  protected:
195   std::string test_extension_id_;
196   // The HTTP server used in the tests.
197   scoped_ptr<EmbeddedTestServer> test_server_;
198   base::ScopedTempDir downloads_dir_;
199 };
200
201 // Tests that navigating to a resource with a MIME type handleable by an
202 // installed, white-listed extension invokes the extension's
203 // onExecuteContentHandler event (and does not start a download).
204 IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Navigate) {
205 #if defined(OS_WIN) && defined(USE_ASH)
206   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
207   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
208     return;
209 #endif
210
211   ASSERT_TRUE(LoadTestExtension()) << message_;
212
213   ResultCatcher catcher;
214
215   ui_test_utils::NavigateToURL(browser(),
216                                test_server_->GetURL("/doc_path.doc"));
217
218   // Wait for the response from the test server.
219   base::MessageLoop::current()->RunUntilIdle();
220
221   // There should be no downloads started by the navigation.
222   DownloadManager* download_manager = GetDownloadManager();
223   std::vector<DownloadItem*> downloads;
224   download_manager->GetAllDownloads(&downloads);
225   ASSERT_EQ(0u, downloads.size());
226
227   // The test extension should receive onExecuteContentHandler event with MIME
228   // type 'application/msword' (and call chrome.test.notifySuccess).
229   EXPECT_TRUE(catcher.GetNextResult());
230 }
231
232 // Tests that navigation to an attachment starts a download, even if there is an
233 // extension with a file browser handler that can handle the attachment's MIME
234 // type.
235 IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, NavigateToAnAttachment) {
236   InitializeDownloadSettings();
237
238   ASSERT_TRUE(LoadTestExtension()) << message_;
239
240   ResultCatcher catcher;
241
242   // The test should start a downloadm.
243   DownloadManager* download_manager = GetDownloadManager();
244   scoped_ptr<content::DownloadTestObserver> download_observer(
245       new content::DownloadTestObserverInProgress(download_manager, 1));
246
247   ui_test_utils::NavigateToURL(browser(),
248                                test_server_->GetURL("/text_path_attch.txt"));
249
250   // Wait for the download to start.
251   download_observer->WaitForFinished();
252
253   // There should be one download started by the navigation.
254   DownloadManager::DownloadVector downloads;
255   download_manager->GetAllDownloads(&downloads);
256   ASSERT_EQ(1u, downloads.size());
257
258   // Cancel and delete the download started in the test.
259   DeleteDownloadAndWaitForFlush(downloads[0], download_manager);
260
261   // The test extension should not receive any events by now. Send it an event
262   // with MIME type "test/done", so it stops waiting for the events. (If there
263   // was an event with MIME type 'plain/text', |catcher.GetNextResult()| will
264   // fail regardless of the sent event; chrome.test.notifySuccess will not be
265   // called by the extension).
266   SendDoneEvent();
267   EXPECT_TRUE(catcher.GetNextResult());
268 }
269
270 // Tests that direct download requests don't get intercepted by
271 // StreamsResourceThrottle, even if there is an extension with a file
272 // browser handler that can handle the download's MIME type.
273 IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, DirectDownload) {
274   InitializeDownloadSettings();
275
276   ASSERT_TRUE(LoadTestExtension()) << message_;
277
278   ResultCatcher catcher;
279
280   DownloadManager* download_manager = GetDownloadManager();
281   scoped_ptr<content::DownloadTestObserver> download_observer(
282       new content::DownloadTestObserverInProgress(download_manager, 1));
283
284   // The resource's URL on the test server.
285   GURL url = test_server_->GetURL("/text_path.txt");
286
287   // The download's target file path.
288   base::FilePath target_path =
289       downloads_dir_.path().Append(FILE_PATH_LITERAL("download_target.txt"));
290
291   // Set the downloads parameters.
292   content::WebContents* web_contents =
293       browser()->tab_strip_model()->GetActiveWebContents();
294   ASSERT_TRUE(web_contents);
295   scoped_ptr<DownloadUrlParameters> params(
296       DownloadUrlParameters::FromWebContents(web_contents, url));
297   params->set_file_path(target_path);
298
299   // Start download of the URL with a path "/text_path.txt" on the test server.
300   download_manager->DownloadUrl(params.Pass());
301
302   // Wait for the download to start.
303   download_observer->WaitForFinished();
304
305   // There should have been one download.
306   std::vector<DownloadItem*> downloads;
307   download_manager->GetAllDownloads(&downloads);
308   ASSERT_EQ(1u, downloads.size());
309
310   // Cancel and delete the download statred in the test.
311   DeleteDownloadAndWaitForFlush(downloads[0], download_manager);
312
313   // The test extension should not receive any events by now. Send it an event
314   // with MIME type "test/done", so it stops waiting for the events. (If there
315   // was an event with MIME type 'plain/text', |catcher.GetNextResult()| will
316   // fail regardless of the sent event; chrome.test.notifySuccess will not be
317   // called by the extension).
318   SendDoneEvent();
319   EXPECT_TRUE(catcher.GetNextResult());
320 }
321
322 }  // namespace