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 <list>
6#include <set>
7
8#include "base/files/scoped_temp_dir.h"
9#include "base/memory/ref_counted.h"
10#include "base/memory/weak_ptr.h"
11#include "base/strings/string_util.h"
12#include "base/strings/stringprintf.h"
13#include "base/strings/utf_string_conversions.h"
14#include "chrome/app/chrome_command_ids.h"
15#include "chrome/browser/browser_process.h"
16#include "chrome/browser/chrome_browser_main.h"
17#include "chrome/browser/chrome_browser_main_extra_parts.h"
18#include "chrome/browser/chrome_content_browser_client.h"
19#include "chrome/browser/chrome_notification_types.h"
20#include "chrome/browser/download/download_browsertest.h"
21#include "chrome/browser/download/download_prefs.h"
22#include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
23#include "chrome/browser/extensions/extension_apitest.h"
24#include "chrome/browser/extensions/extension_service.h"
25#include "chrome/browser/profiles/profile.h"
26#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
27#include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
28#include "chrome/browser/ui/browser.h"
29#include "chrome/browser/ui/tabs/tab_strip_model.h"
30#include "chrome/test/base/ui_test_utils.h"
31#include "content/public/browser/browser_thread.h"
32#include "content/public/browser/render_frame_host.h"
33#include "content/public/browser/render_process_host.h"
34#include "content/public/browser/render_view_host.h"
35#include "content/public/browser/resource_controller.h"
36#include "content/public/browser/resource_dispatcher_host.h"
37#include "content/public/browser/resource_throttle.h"
38#include "content/public/browser/web_contents.h"
39#include "content/public/common/context_menu_params.h"
40#include "content/public/common/resource_type.h"
41#include "content/public/common/url_constants.h"
42#include "content/public/test/browser_test_utils.h"
43#include "extensions/browser/extension_system.h"
44#include "extensions/common/switches.h"
45#include "extensions/test/result_catcher.h"
46#include "net/dns/mock_host_resolver.h"
47#include "net/test/embedded_test_server/embedded_test_server.h"
48#include "third_party/WebKit/public/web/WebContextMenuData.h"
49#include "third_party/WebKit/public/web/WebInputEvent.h"
50
51using content::ResourceType;
52using content::WebContents;
53
54namespace extensions {
55
56namespace {
57
58// This class can defer requests for arbitrary URLs.
59class TestNavigationListener
60    : public base::RefCountedThreadSafe<TestNavigationListener> {
61 public:
62  TestNavigationListener() {}
63
64  // Add |url| to the set of URLs we should delay.
65  void DelayRequestsForURL(const GURL& url) {
66    if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
67      content::BrowserThread::PostTask(
68          content::BrowserThread::IO,
69          FROM_HERE,
70          base::Bind(&TestNavigationListener::DelayRequestsForURL, this, url));
71      return;
72    }
73    urls_to_delay_.insert(url);
74  }
75
76  // Resume all deferred requests.
77  void ResumeAll() {
78    if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
79      content::BrowserThread::PostTask(
80          content::BrowserThread::IO,
81          FROM_HERE,
82          base::Bind(&TestNavigationListener::ResumeAll, this));
83      return;
84    }
85    WeakThrottleList::const_iterator it;
86    for (it = throttles_.begin(); it != throttles_.end(); ++it) {
87      if (it->get())
88        (*it)->Resume();
89    }
90    throttles_.clear();
91  }
92
93  // Constructs a ResourceThrottle if the request for |url| should be held.
94  //
95  // Needs to be invoked on the IO thread.
96  content::ResourceThrottle* CreateResourceThrottle(
97      const GURL& url,
98      ResourceType resource_type) {
99    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
100    if (urls_to_delay_.find(url) == urls_to_delay_.end())
101      return NULL;
102
103    Throttle* throttle = new Throttle();
104    throttles_.push_back(throttle->AsWeakPtr());
105    return throttle;
106  }
107
108 private:
109  friend class base::RefCountedThreadSafe<TestNavigationListener>;
110
111  virtual ~TestNavigationListener() {}
112
113  // Stores a throttle per URL request that we have delayed.
114  class Throttle : public content::ResourceThrottle,
115                   public base::SupportsWeakPtr<Throttle> {
116   public:
117    void Resume() {
118      controller()->Resume();
119    }
120
121    // content::ResourceThrottle implementation.
122    virtual void WillStartRequest(bool* defer) OVERRIDE {
123      *defer = true;
124    }
125
126    virtual const char* GetNameForLogging() const OVERRIDE {
127      return "TestNavigationListener::Throttle";
128    }
129  };
130  typedef base::WeakPtr<Throttle> WeakThrottle;
131  typedef std::list<WeakThrottle> WeakThrottleList;
132  WeakThrottleList throttles_;
133
134  // The set of URLs to be delayed.
135  std::set<GURL> urls_to_delay_;
136
137  DISALLOW_COPY_AND_ASSIGN(TestNavigationListener);
138};
139
140// Waits for a WC to be created. Once it starts loading |delay_url| (after at
141// least the first navigation has committed), it delays the load, executes
142// |script| in the last committed RVH and resumes the load when a URL ending in
143// |until_url_suffix| commits. This class expects |script| to trigger the load
144// of an URL ending in |until_url_suffix|.
145class DelayLoadStartAndExecuteJavascript
146    : public content::NotificationObserver,
147      public content::WebContentsObserver {
148 public:
149  DelayLoadStartAndExecuteJavascript(
150      TestNavigationListener* test_navigation_listener,
151      const GURL& delay_url,
152      const std::string& script,
153      const std::string& until_url_suffix)
154      : content::WebContentsObserver(),
155        test_navigation_listener_(test_navigation_listener),
156        delay_url_(delay_url),
157        until_url_suffix_(until_url_suffix),
158        script_(script),
159        script_was_executed_(false),
160        rvh_(NULL) {
161    registrar_.Add(this,
162                   chrome::NOTIFICATION_TAB_ADDED,
163                   content::NotificationService::AllSources());
164    test_navigation_listener_->DelayRequestsForURL(delay_url_);
165  }
166  virtual ~DelayLoadStartAndExecuteJavascript() {}
167
168  virtual void Observe(int type,
169                       const content::NotificationSource& source,
170                       const content::NotificationDetails& details) OVERRIDE {
171    if (type != chrome::NOTIFICATION_TAB_ADDED) {
172      NOTREACHED();
173      return;
174    }
175    content::WebContentsObserver::Observe(
176        content::Details<content::WebContents>(details).ptr());
177    registrar_.RemoveAll();
178  }
179
180  virtual void DidStartProvisionalLoadForFrame(
181      content::RenderFrameHost* render_frame_host,
182      const GURL& validated_url,
183      bool is_error_page,
184      bool is_iframe_srcdoc) OVERRIDE {
185    if (validated_url != delay_url_ || !rvh_)
186      return;
187
188    rvh_->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(script_));
189    script_was_executed_ = true;
190  }
191
192  virtual void DidCommitProvisionalLoadForFrame(
193      content::RenderFrameHost* render_frame_host,
194      const GURL& url,
195      ui::PageTransition transition_type) OVERRIDE {
196    if (script_was_executed_ && EndsWith(url.spec(), until_url_suffix_, true)) {
197      content::WebContentsObserver::Observe(NULL);
198      test_navigation_listener_->ResumeAll();
199    }
200    rvh_ = render_frame_host->GetRenderViewHost();
201  }
202
203 private:
204  content::NotificationRegistrar registrar_;
205
206  scoped_refptr<TestNavigationListener> test_navigation_listener_;
207
208  GURL delay_url_;
209  std::string until_url_suffix_;
210  std::string script_;
211  bool script_was_executed_;
212  content::RenderViewHost* rvh_;
213
214  DISALLOW_COPY_AND_ASSIGN(DelayLoadStartAndExecuteJavascript);
215};
216
217// A ResourceDispatcherHostDelegate that adds a TestNavigationObserver.
218class TestResourceDispatcherHostDelegate
219    : public ChromeResourceDispatcherHostDelegate {
220 public:
221  TestResourceDispatcherHostDelegate(
222      prerender::PrerenderTracker* prerender_tracker,
223      TestNavigationListener* test_navigation_listener)
224      : ChromeResourceDispatcherHostDelegate(prerender_tracker),
225        test_navigation_listener_(test_navigation_listener) {
226  }
227  virtual ~TestResourceDispatcherHostDelegate() {}
228
229  virtual void RequestBeginning(
230      net::URLRequest* request,
231      content::ResourceContext* resource_context,
232      content::AppCacheService* appcache_service,
233      ResourceType resource_type,
234      ScopedVector<content::ResourceThrottle>* throttles) OVERRIDE {
235    ChromeResourceDispatcherHostDelegate::RequestBeginning(
236        request,
237        resource_context,
238        appcache_service,
239        resource_type,
240        throttles);
241    content::ResourceThrottle* throttle =
242        test_navigation_listener_->CreateResourceThrottle(request->url(),
243                                                          resource_type);
244    if (throttle)
245      throttles->push_back(throttle);
246  }
247
248 private:
249  scoped_refptr<TestNavigationListener> test_navigation_listener_;
250
251  DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate);
252};
253
254}  // namespace
255
256class WebNavigationApiTest : public ExtensionApiTest {
257 public:
258  WebNavigationApiTest() {}
259  virtual ~WebNavigationApiTest() {}
260
261  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
262    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
263
264    FrameNavigationState::set_allow_extension_scheme(true);
265
266    CommandLine::ForCurrentProcess()->AppendSwitch(
267        switches::kAllowLegacyExtensionManifests);
268
269    host_resolver()->AddRule("*", "127.0.0.1");
270  }
271
272  virtual void SetUpOnMainThread() OVERRIDE {
273    ExtensionApiTest::SetUpOnMainThread();
274    test_navigation_listener_ = new TestNavigationListener();
275    resource_dispatcher_host_delegate_.reset(
276        new TestResourceDispatcherHostDelegate(
277            g_browser_process->prerender_tracker(),
278            test_navigation_listener_.get()));
279    content::ResourceDispatcherHost::Get()->SetDelegate(
280        resource_dispatcher_host_delegate_.get());
281  }
282
283  TestNavigationListener* test_navigation_listener() {
284    return test_navigation_listener_.get();
285  }
286
287 private:
288  scoped_refptr<TestNavigationListener> test_navigation_listener_;
289  scoped_ptr<TestResourceDispatcherHostDelegate>
290      resource_dispatcher_host_delegate_;
291
292  DISALLOW_COPY_AND_ASSIGN(WebNavigationApiTest);
293};
294
295IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Api) {
296  ASSERT_TRUE(StartEmbeddedTestServer());
297  ASSERT_TRUE(RunExtensionTest("webnavigation/api")) << message_;
298}
299
300IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, GetFrame) {
301  ASSERT_TRUE(StartEmbeddedTestServer());
302  ASSERT_TRUE(RunExtensionTest("webnavigation/getFrame")) << message_;
303}
304
305IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ClientRedirect) {
306  ASSERT_TRUE(StartEmbeddedTestServer());
307  ASSERT_TRUE(RunExtensionTest("webnavigation/clientRedirect"))
308      << message_;
309}
310
311IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ServerRedirect) {
312  ASSERT_TRUE(StartEmbeddedTestServer());
313  ASSERT_TRUE(RunExtensionTest("webnavigation/serverRedirect"))
314      << message_;
315}
316
317IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Download) {
318  base::ScopedTempDir download_directory;
319  ASSERT_TRUE(download_directory.CreateUniqueTempDir());
320  DownloadPrefs* download_prefs =
321      DownloadPrefs::FromBrowserContext(browser()->profile());
322  download_prefs->SetDownloadPath(download_directory.path());
323
324  DownloadTestObserverNotInProgress download_observer(
325      content::BrowserContext::GetDownloadManager(profile()), 1);
326  download_observer.StartObserving();
327  ASSERT_TRUE(StartEmbeddedTestServer());
328  ASSERT_TRUE(RunExtensionTest("webnavigation/download"))
329      << message_;
330  download_observer.WaitForFinished();
331}
332
333IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ServerRedirectSingleProcess) {
334  ASSERT_TRUE(StartEmbeddedTestServer());
335
336  // Set max renderers to 1 to force running out of processes.
337  content::RenderProcessHost::SetMaxRendererProcessCount(1);
338
339  // Wait for the extension to set itself up and return control to us.
340  ASSERT_TRUE(
341      RunExtensionTest("webnavigation/serverRedirectSingleProcess"))
342      << message_;
343
344  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
345  content::WaitForLoadStop(tab);
346
347  ResultCatcher catcher;
348  GURL url(base::StringPrintf(
349      "http://www.a.com:%d/"
350      "extensions/api_test/webnavigation/serverRedirectSingleProcess/a.html",
351      embedded_test_server()->port()));
352
353  ui_test_utils::NavigateToURL(browser(), url);
354
355  url = GURL(base::StringPrintf(
356      "http://www.b.com:%d/server-redirect?http://www.b.com:%d/",
357      embedded_test_server()->port(),
358      embedded_test_server()->port()));
359
360  ui_test_utils::NavigateToURL(browser(), url);
361
362  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
363}
364
365IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ForwardBack) {
366  ASSERT_TRUE(StartEmbeddedTestServer());
367  ASSERT_TRUE(RunExtensionTest("webnavigation/forwardBack")) << message_;
368}
369
370IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, IFrame) {
371  ASSERT_TRUE(StartEmbeddedTestServer());
372  ASSERT_TRUE(RunExtensionTest("webnavigation/iframe")) << message_;
373}
374
375IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, SrcDoc) {
376  ASSERT_TRUE(StartEmbeddedTestServer());
377  ASSERT_TRUE(RunExtensionTest("webnavigation/srcdoc")) << message_;
378}
379
380IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, OpenTab) {
381  ASSERT_TRUE(StartEmbeddedTestServer());
382  ASSERT_TRUE(RunExtensionTest("webnavigation/openTab")) << message_;
383}
384
385IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ReferenceFragment) {
386  ASSERT_TRUE(StartEmbeddedTestServer());
387  ASSERT_TRUE(RunExtensionTest("webnavigation/referenceFragment"))
388      << message_;
389}
390
391IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, SimpleLoad) {
392  ASSERT_TRUE(StartEmbeddedTestServer());
393  ASSERT_TRUE(RunExtensionTest("webnavigation/simpleLoad")) << message_;
394}
395
396IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Failures) {
397  ASSERT_TRUE(StartEmbeddedTestServer());
398  ASSERT_TRUE(RunExtensionTest("webnavigation/failures")) << message_;
399}
400
401IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, FilteredTest) {
402  ASSERT_TRUE(StartEmbeddedTestServer());
403  ASSERT_TRUE(RunExtensionTest("webnavigation/filtered")) << message_;
404}
405
406IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, UserAction) {
407  ASSERT_TRUE(StartEmbeddedTestServer());
408
409  // Wait for the extension to set itself up and return control to us.
410  ASSERT_TRUE(RunExtensionTest("webnavigation/userAction")) << message_;
411
412  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
413  content::WaitForLoadStop(tab);
414
415  ResultCatcher catcher;
416
417  ExtensionService* service = extensions::ExtensionSystem::Get(
418      browser()->profile())->extension_service();
419  const extensions::Extension* extension =
420      service->GetExtensionById(last_loaded_extension_id(), false);
421  GURL url = extension->GetResourceURL("a.html");
422
423  ui_test_utils::NavigateToURL(browser(), url);
424
425  // This corresponds to "Open link in new tab".
426  content::ContextMenuParams params;
427  params.is_editable = false;
428  params.media_type = blink::WebContextMenuData::MediaTypeNone;
429  params.page_url = url;
430  params.link_url = extension->GetResourceURL("b.html");
431
432  TestRenderViewContextMenu menu(tab->GetMainFrame(), params);
433  menu.Init();
434  menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, 0);
435
436  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
437}
438
439IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, RequestOpenTab) {
440  ASSERT_TRUE(StartEmbeddedTestServer());
441
442  // Wait for the extension to set itself up and return control to us.
443  ASSERT_TRUE(RunExtensionTest("webnavigation/requestOpenTab"))
444      << message_;
445
446  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
447  content::WaitForLoadStop(tab);
448
449  ResultCatcher catcher;
450
451  ExtensionService* service = extensions::ExtensionSystem::Get(
452      browser()->profile())->extension_service();
453  const extensions::Extension* extension =
454      service->GetExtensionById(last_loaded_extension_id(), false);
455  GURL url = extension->GetResourceURL("a.html");
456
457  ui_test_utils::NavigateToURL(browser(), url);
458
459  // There's a link on a.html. Middle-click on it to open it in a new tab.
460  blink::WebMouseEvent mouse_event;
461  mouse_event.type = blink::WebInputEvent::MouseDown;
462  mouse_event.button = blink::WebMouseEvent::ButtonMiddle;
463  mouse_event.x = 7;
464  mouse_event.y = 7;
465  mouse_event.clickCount = 1;
466  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
467  mouse_event.type = blink::WebInputEvent::MouseUp;
468  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
469
470  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
471}
472
473IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, TargetBlank) {
474  ASSERT_TRUE(StartEmbeddedTestServer());
475
476  // Wait for the extension to set itself up and return control to us.
477  ASSERT_TRUE(RunExtensionTest("webnavigation/targetBlank")) << message_;
478
479  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
480  content::WaitForLoadStop(tab);
481
482  ResultCatcher catcher;
483
484  GURL url = embedded_test_server()->GetURL(
485      "/extensions/api_test/webnavigation/targetBlank/a.html");
486
487  chrome::NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK);
488  ui_test_utils::NavigateToURL(&params);
489
490  // There's a link with target=_blank on a.html. Click on it to open it in a
491  // new tab.
492  blink::WebMouseEvent mouse_event;
493  mouse_event.type = blink::WebInputEvent::MouseDown;
494  mouse_event.button = blink::WebMouseEvent::ButtonLeft;
495  mouse_event.x = 7;
496  mouse_event.y = 7;
497  mouse_event.clickCount = 1;
498  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
499  mouse_event.type = blink::WebInputEvent::MouseUp;
500  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
501
502  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
503}
504
505IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, TargetBlankIncognito) {
506  ASSERT_TRUE(StartEmbeddedTestServer());
507
508  // Wait for the extension to set itself up and return control to us.
509  ASSERT_TRUE(RunExtensionTestIncognito("webnavigation/targetBlank"))
510      << message_;
511
512  ResultCatcher catcher;
513
514  GURL url = embedded_test_server()->GetURL(
515      "/extensions/api_test/webnavigation/targetBlank/a.html");
516
517  Browser* otr_browser = ui_test_utils::OpenURLOffTheRecord(
518      browser()->profile(), url);
519  WebContents* tab = otr_browser->tab_strip_model()->GetActiveWebContents();
520
521  // There's a link with target=_blank on a.html. Click on it to open it in a
522  // new tab.
523  blink::WebMouseEvent mouse_event;
524  mouse_event.type = blink::WebInputEvent::MouseDown;
525  mouse_event.button = blink::WebMouseEvent::ButtonLeft;
526  mouse_event.x = 7;
527  mouse_event.y = 7;
528  mouse_event.clickCount = 1;
529  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
530  mouse_event.type = blink::WebInputEvent::MouseUp;
531  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
532
533  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
534}
535
536IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, History) {
537  ASSERT_TRUE(StartEmbeddedTestServer());
538  ASSERT_TRUE(RunExtensionTest("webnavigation/history")) << message_;
539}
540
541IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcess) {
542  ASSERT_TRUE(StartEmbeddedTestServer());
543
544  LoadExtension(test_data_dir_.AppendASCII("webnavigation").AppendASCII("app"));
545
546  // See crossProcess/d.html.
547  DelayLoadStartAndExecuteJavascript call_script(
548      test_navigation_listener(),
549      embedded_test_server()->GetURL("/test1"),
550      "navigate2()",
551      "empty.html");
552
553  ASSERT_TRUE(RunExtensionTest("webnavigation/crossProcess")) << message_;
554}
555
556IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessFragment) {
557  ASSERT_TRUE(StartEmbeddedTestServer());
558
559  // See crossProcessFragment/f.html.
560  DelayLoadStartAndExecuteJavascript call_script3(
561      test_navigation_listener(),
562      embedded_test_server()->GetURL("/test3"),
563      "updateFragment()",
564      base::StringPrintf("f.html?%d#foo", embedded_test_server()->port()));
565
566  // See crossProcessFragment/g.html.
567  DelayLoadStartAndExecuteJavascript call_script4(
568      test_navigation_listener(),
569      embedded_test_server()->GetURL("/test4"),
570      "updateFragment()",
571      base::StringPrintf("g.html?%d#foo", embedded_test_server()->port()));
572
573  ASSERT_TRUE(RunExtensionTest("webnavigation/crossProcessFragment"))
574      << message_;
575}
576
577IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessHistory) {
578  ASSERT_TRUE(StartEmbeddedTestServer());
579
580  // See crossProcessHistory/e.html.
581  DelayLoadStartAndExecuteJavascript call_script2(
582      test_navigation_listener(),
583      embedded_test_server()->GetURL("/test2"),
584      "updateHistory()",
585      "empty.html");
586
587  // See crossProcessHistory/h.html.
588  DelayLoadStartAndExecuteJavascript call_script5(
589      test_navigation_listener(),
590      embedded_test_server()->GetURL("/test5"),
591      "updateHistory()",
592      "empty.html");
593
594  // See crossProcessHistory/i.html.
595  DelayLoadStartAndExecuteJavascript call_script6(
596      test_navigation_listener(),
597      embedded_test_server()->GetURL("/test6"),
598      "updateHistory()",
599      "empty.html");
600
601  ASSERT_TRUE(RunExtensionTest("webnavigation/crossProcessHistory"))
602      << message_;
603}
604
605// TODO(jam): http://crbug.com/350550
606#if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER))
607IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Crash) {
608  ASSERT_TRUE(StartEmbeddedTestServer());
609
610  // Wait for the extension to set itself up and return control to us.
611  ASSERT_TRUE(RunExtensionTest("webnavigation/crash")) << message_;
612
613  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
614  content::WaitForLoadStop(tab);
615
616  ResultCatcher catcher;
617
618  GURL url(base::StringPrintf(
619      "http://www.a.com:%d/"
620          "extensions/api_test/webnavigation/crash/a.html",
621      embedded_test_server()->port()));
622  ui_test_utils::NavigateToURL(browser(), url);
623
624  ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
625
626  url = GURL(base::StringPrintf(
627      "http://www.a.com:%d/"
628          "extensions/api_test/webnavigation/crash/b.html",
629      embedded_test_server()->port()));
630  ui_test_utils::NavigateToURL(browser(), url);
631
632  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
633}
634
635#endif
636
637}  // namespace extensions
638