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 "chrome/browser/chrome_notification_types.h"
7#include "chrome/browser/extensions/extension_apitest.h"
8#include "chrome/browser/extensions/extension_service.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/ui/browser.h"
11#include "chrome/browser/ui/login/login_prompt.h"
12#include "chrome/browser/ui/tabs/tab_strip_model.h"
13#include "chrome/test/base/ui_test_utils.h"
14#include "content/public/browser/notification_registrar.h"
15#include "content/public/browser/notification_service.h"
16#include "content/public/browser/render_view_host.h"
17#include "content/public/browser/web_contents.h"
18#include "content/public/test/browser_test_utils.h"
19#include "extensions/browser/api/web_request/web_request_api.h"
20#include "extensions/browser/extension_system.h"
21#include "extensions/common/features/feature.h"
22#include "extensions/test/extension_test_message_listener.h"
23#include "extensions/test/result_catcher.h"
24#include "net/dns/mock_host_resolver.h"
25#include "net/test/embedded_test_server/embedded_test_server.h"
26#include "third_party/WebKit/public/web/WebInputEvent.h"
27
28using content::WebContents;
29using extensions::Feature;
30using extensions::ResultCatcher;
31
32namespace {
33
34class CancelLoginDialog : public content::NotificationObserver {
35 public:
36  CancelLoginDialog() {
37    registrar_.Add(this,
38                   chrome::NOTIFICATION_AUTH_NEEDED,
39                   content::NotificationService::AllSources());
40  }
41
42  virtual ~CancelLoginDialog() {}
43
44  virtual void Observe(int type,
45                       const content::NotificationSource& source,
46                       const content::NotificationDetails& details) OVERRIDE {
47    LoginHandler* handler =
48        content::Details<LoginNotificationDetails>(details).ptr()->handler();
49    handler->CancelAuth();
50  }
51
52 private:
53  content::NotificationRegistrar registrar_;
54
55 DISALLOW_COPY_AND_ASSIGN(CancelLoginDialog);
56};
57
58}  // namespace
59
60class ExtensionWebRequestApiTest : public ExtensionApiTest {
61 public:
62  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
63    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
64    host_resolver()->AddRule("*", "127.0.0.1");
65  }
66
67  void RunPermissionTest(
68      const char* extension_directory,
69      bool load_extension_with_incognito_permission,
70      bool wait_for_extension_loaded_in_incognito,
71      const char* expected_content_regular_window,
72      const char* exptected_content_incognito_window);
73};
74
75IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestApi) {
76  ASSERT_TRUE(StartEmbeddedTestServer());
77  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_api.html")) << message_;
78}
79
80// Fails often on Windows dbg bots. http://crbug.com/177163
81#if defined(OS_WIN)
82#define MAYBE_WebRequestSimple DISABLED_WebRequestSimple
83#else
84#define MAYBE_WebRequestSimple WebRequestSimple
85#endif  // defined(OS_WIN)
86IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestSimple) {
87  ASSERT_TRUE(StartEmbeddedTestServer());
88  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_simple.html")) <<
89      message_;
90}
91
92IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestComplex) {
93  ASSERT_TRUE(StartEmbeddedTestServer());
94  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_complex.html")) <<
95      message_;
96}
97
98// Flaky (sometimes crash): http://crbug.com/140976
99IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
100                       DISABLED_WebRequestAuthRequired) {
101  CancelLoginDialog login_dialog_helper;
102
103  ASSERT_TRUE(StartEmbeddedTestServer());
104  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_auth_required.html")) <<
105      message_;
106}
107
108// This test times out regularly on win_rel trybots. See http://crbug.com/122178
109#if defined(OS_WIN)
110#define MAYBE_WebRequestBlocking DISABLED_WebRequestBlocking
111#else
112#define MAYBE_WebRequestBlocking WebRequestBlocking
113#endif
114IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestBlocking) {
115  ASSERT_TRUE(StartEmbeddedTestServer());
116  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_blocking.html")) <<
117      message_;
118}
119
120// Fails often on Windows dbg bots. http://crbug.com/177163
121#if defined(OS_WIN)
122#define MAYBE_WebRequestNewTab DISABLED_WebRequestNewTab
123#else
124#define MAYBE_WebRequestNewTab WebRequestNewTab
125#endif  // defined(OS_WIN)
126IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestNewTab) {
127  ASSERT_TRUE(StartEmbeddedTestServer());
128  // Wait for the extension to set itself up and return control to us.
129  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_newTab.html"))
130      << message_;
131
132  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
133  content::WaitForLoadStop(tab);
134
135  ResultCatcher catcher;
136
137  ExtensionService* service = extensions::ExtensionSystem::Get(
138      browser()->profile())->extension_service();
139  const extensions::Extension* extension =
140      service->GetExtensionById(last_loaded_extension_id(), false);
141  GURL url = extension->GetResourceURL("newTab/a.html");
142
143  ui_test_utils::NavigateToURL(browser(), url);
144
145  // There's a link on a.html with target=_blank. Click on it to open it in a
146  // new tab.
147  blink::WebMouseEvent mouse_event;
148  mouse_event.type = blink::WebInputEvent::MouseDown;
149  mouse_event.button = blink::WebMouseEvent::ButtonLeft;
150  mouse_event.x = 7;
151  mouse_event.y = 7;
152  mouse_event.clickCount = 1;
153  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
154  mouse_event.type = blink::WebInputEvent::MouseUp;
155  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
156
157  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
158}
159
160IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestDeclarative1) {
161  ASSERT_TRUE(StartEmbeddedTestServer());
162  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative1.html"))
163      << message_;
164}
165
166// This test times out on XP. See http://crbug.com/178296
167#if defined(OS_WIN)
168#define MAYBE_WebRequestDeclarative2 DISABLED_WebRequestDeclarative2
169#else
170#define MAYBE_WebRequestDeclarative2 WebRequestDeclarative2
171#endif
172IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
173                       MAYBE_WebRequestDeclarative2) {
174  ASSERT_TRUE(StartEmbeddedTestServer());
175  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative2.html"))
176      << message_;
177}
178
179void ExtensionWebRequestApiTest::RunPermissionTest(
180    const char* extension_directory,
181    bool load_extension_with_incognito_permission,
182    bool wait_for_extension_loaded_in_incognito,
183    const char* expected_content_regular_window,
184    const char* exptected_content_incognito_window) {
185  ResultCatcher catcher;
186  catcher.RestrictToBrowserContext(browser()->profile());
187  ResultCatcher catcher_incognito;
188  catcher_incognito.RestrictToBrowserContext(
189      browser()->profile()->GetOffTheRecordProfile());
190
191  ExtensionTestMessageListener listener("done", true);
192  ExtensionTestMessageListener listener_incognito("done_incognito", true);
193
194  int load_extension_flags = kFlagNone;
195  if (load_extension_with_incognito_permission)
196    load_extension_flags |= kFlagEnableIncognito;
197  ASSERT_TRUE(LoadExtensionWithFlags(
198      test_data_dir_.AppendASCII("webrequest_permissions")
199                    .AppendASCII(extension_directory),
200      load_extension_flags));
201
202  // Test that navigation in regular window is properly redirected.
203  EXPECT_TRUE(listener.WaitUntilSatisfied());
204
205  // This navigation should be redirected.
206  ui_test_utils::NavigateToURL(
207      browser(),
208      embedded_test_server()->GetURL("/extensions/test_file.html"));
209
210  std::string body;
211  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
212  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
213        tab,
214        "window.domAutomationController.send(document.body.textContent)",
215        &body));
216  EXPECT_EQ(expected_content_regular_window, body);
217
218  // Test that navigation in OTR window is properly redirected.
219  Browser* otr_browser = ui_test_utils::OpenURLOffTheRecord(
220      browser()->profile(), GURL("about:blank"));
221
222  if (wait_for_extension_loaded_in_incognito)
223    EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
224
225  // This navigation should be redirected if
226  // load_extension_with_incognito_permission is true.
227  ui_test_utils::NavigateToURL(
228      otr_browser,
229      embedded_test_server()->GetURL("/extensions/test_file.html"));
230
231  body.clear();
232  WebContents* otr_tab = otr_browser->tab_strip_model()->GetActiveWebContents();
233  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
234      otr_tab,
235      "window.domAutomationController.send(document.body.textContent)",
236      &body));
237  EXPECT_EQ(exptected_content_incognito_window, body);
238}
239
240IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
241                       WebRequestDeclarativePermissionSpanning1) {
242  // Test spanning with incognito permission.
243  ASSERT_TRUE(StartEmbeddedTestServer());
244  RunPermissionTest("spanning", true, false, "redirected1", "redirected1");
245}
246
247IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
248                       WebRequestDeclarativePermissionSpanning2) {
249  // Test spanning without incognito permission.
250  ASSERT_TRUE(StartEmbeddedTestServer());
251  RunPermissionTest("spanning", false, false, "redirected1", "");
252}
253
254
255IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
256                       WebRequestDeclarativePermissionSplit1) {
257  // Test split with incognito permission.
258  ASSERT_TRUE(StartEmbeddedTestServer());
259  RunPermissionTest("split", true, true, "redirected1", "redirected2");
260}
261
262IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
263                       WebRequestDeclarativePermissionSplit2) {
264  // Test split without incognito permission.
265  ASSERT_TRUE(StartEmbeddedTestServer());
266  RunPermissionTest("split", false, false, "redirected1", "");
267}
268
269// TODO(vabr): Cure these flaky tests, http://crbug.com/238179.
270#if !defined(NDEBUG)
271#define MAYBE_PostData1 DISABLED_PostData1
272#define MAYBE_PostData2 DISABLED_PostData2
273#else
274#define MAYBE_PostData1 PostData1
275#define MAYBE_PostData2 PostData2
276#endif
277IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_PostData1) {
278  // Test HTML form POST data access with the default and "url" encoding.
279  ASSERT_TRUE(StartEmbeddedTestServer());
280  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_post1.html")) <<
281      message_;
282}
283
284IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_PostData2) {
285  // Test HTML form POST data access with the multipart and plaintext encoding.
286  ASSERT_TRUE(StartEmbeddedTestServer());
287  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_post2.html")) <<
288      message_;
289}
290
291IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
292                       DeclarativeSendMessage) {
293  ASSERT_TRUE(StartEmbeddedTestServer());
294  ASSERT_TRUE(RunExtensionTest("webrequest_sendmessage")) << message_;
295}
296
297// Check that reloading an extension that runs in incognito split mode and
298// has two active background pages with registered events does not crash the
299// browser. Regression test for http://crbug.com/224094
300IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, IncognitoSplitModeReload) {
301  ASSERT_TRUE(StartEmbeddedTestServer());
302  // Wait for rules to be set up.
303  ExtensionTestMessageListener listener("done", true);
304  ExtensionTestMessageListener listener_incognito("done_incognito", true);
305
306  const extensions::Extension* extension = LoadExtensionWithFlags(
307      test_data_dir_.AppendASCII("webrequest_reload"),
308      kFlagEnableIncognito);
309  ASSERT_TRUE(extension);
310  ui_test_utils::OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
311
312  EXPECT_TRUE(listener.WaitUntilSatisfied());
313  EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
314
315  // Reload extension and wait for rules to be set up again. This should not
316  // crash the browser.
317  ExtensionTestMessageListener listener2("done", true);
318  ExtensionTestMessageListener listener_incognito2("done_incognito", true);
319
320  ReloadExtension(extension->id());
321
322  EXPECT_TRUE(listener2.WaitUntilSatisfied());
323  EXPECT_TRUE(listener_incognito2.WaitUntilSatisfied());
324}
325