1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/command_line.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/stringprintf.h"
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/loader/resource_dispatcher_host_impl.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/resource_dispatcher_host_delegate.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/resource_throttle.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/web_contents.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/common/content_switches.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/test/browser_test_utils.h"
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/test/content_browser_test.h"
15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/test/content_browser_test_utils.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/test/test_navigation_observer.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/shell/browser/shell.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/shell/browser/shell_content_browser_client.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/escape.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/dns/mock_host_resolver.h"
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request.h"
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request_status.h"
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/gurl.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Tracks a single request for a specified URL, and allows waiting until the
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// request is destroyed, and then inspecting whether it completed successfully.
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class TrackingResourceDispatcherHostDelegate
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : public ShellResourceDispatcherHostDelegate {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TrackingResourceDispatcherHostDelegate() : throttle_created_(false) {
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void RequestBeginning(
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      net::URLRequest* request,
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ResourceContext* resource_context,
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      AppCacheService* appcache_service,
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ResourceType resource_type,
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ShellResourceDispatcherHostDelegate::RequestBeginning(
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        request, resource_context, appcache_service, resource_type, throttles);
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Expect only a single request for the tracked url.
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ASSERT_FALSE(throttle_created_);
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // If this is a request for the tracked URL, add a throttle to track it.
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (request->url() == tracked_url_)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      throttles->push_back(new TrackingThrottle(request, this));
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Starts tracking a URL.  The request for previously tracked URL, if any,
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // must have been made and deleted before calling this function.
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetTrackedURL(const GURL& tracked_url) {
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Should not currently be tracking any URL.
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ASSERT_FALSE(run_loop_);
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Create a RunLoop that will be stopped once the request for the tracked
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // URL has been destroyed, to allow tracking the URL while also waiting for
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // other events.
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    run_loop_.reset(new base::RunLoop());
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserThread::PostTask(
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            &TrackingResourceDispatcherHostDelegate::SetTrackedURLOnIOThread,
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::Unretained(this),
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            tracked_url));
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Waits until the tracked URL has been requests, and the request for it has
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // been destroyed.
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool WaitForTrackedURLAndGetCompleted() {
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    run_loop_->Run();
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    run_loop_.reset();
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return tracked_request_completed_;
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // ResourceThrottle attached to request for the tracked URL.  On destruction,
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // passes the final URLRequestStatus back to the delegate.
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  class TrackingThrottle : public ResourceThrottle {
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   public:
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TrackingThrottle(net::URLRequest* request,
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     TrackingResourceDispatcherHostDelegate* tracker)
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        : request_(request), tracker_(tracker) {
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    virtual ~TrackingThrottle() {
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // If the request is deleted without being cancelled, its status will
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // indicate it succeeded, so have to check if the request is still pending
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // as well.
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      tracker_->OnTrackedRequestDestroyed(
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          !request_->is_pending() && request_->status().is_success());
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // ResourceThrottle implementation:
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    virtual const char* GetNameForLogging() const OVERRIDE {
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "TrackingThrottle";
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   private:
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLRequest* request_;
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TrackingResourceDispatcherHostDelegate* tracker_;
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(TrackingThrottle);
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetTrackedURLOnIOThread(const GURL& tracked_url) {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    throttle_created_ = false;
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    tracked_url_ = tracked_url;
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnTrackedRequestDestroyed(bool completed) {
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    tracked_request_completed_ = completed;
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    tracked_url_ = GURL();
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserThread::PostTask(
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        BrowserThread::UI, FROM_HERE, run_loop_->QuitClosure());
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // These live on the IO thread.
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL tracked_url_;
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool throttle_created_;
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This is created and destroyed on the UI thread, but stopped on the IO
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // thread.
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_;
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Set on the IO thread while |run_loop_| is non-NULL, read on the UI thread
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // after deleting run_loop_.
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool tracked_request_completed_;
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TrackingResourceDispatcherHostDelegate);
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// WebContentsDelegate that fails to open a URL when there's a request that
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// needs to be transferred between renderers.
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class NoTransferRequestDelegate : public WebContentsDelegate {
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NoTransferRequestDelegate() {}
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual WebContents* OpenURLFromTab(WebContents* source,
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      const OpenURLParams& params) OVERRIDE {
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool is_transfer =
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        (params.transferred_global_request_id != GlobalRequestID());
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (is_transfer)
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return NULL;
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NavigationController::LoadURLParams load_url_params(params.url);
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    load_url_params.referrer = params.referrer;
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    load_url_params.frame_tree_node_id = params.frame_tree_node_id;
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    load_url_params.transition_type = params.transition;
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    load_url_params.extra_headers = params.extra_headers;
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    load_url_params.should_replace_current_entry =
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        params.should_replace_current_entry;
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    load_url_params.is_renderer_initiated = true;
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    source->GetController().LoadURLWithParams(load_url_params);
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return source;
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NoTransferRequestDelegate);
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class CrossSiteTransferTest : public ContentBrowserTest {
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CrossSiteTransferTest() : old_delegate_(NULL) {
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // ContentBrowserTest implementation:
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void SetUpOnMainThread() OVERRIDE {
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserThread::PostTask(
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            &CrossSiteTransferTest::InjectResourceDisptcherHostDelegate,
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::Unretained(this)));
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void TearDownOnMainThread() OVERRIDE {
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserThread::PostTask(
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            &CrossSiteTransferTest::RestoreResourceDisptcherHostDelegate,
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::Unretained(this)));
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected:
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void NavigateToURLContentInitiated(Shell* window,
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     const GURL& url,
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     bool should_replace_current_entry,
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     bool should_wait_for_navigation) {
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    std::string script;
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (should_replace_current_entry)
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      script = base::StringPrintf("location.replace('%s')", url.spec().c_str());
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    else
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      script = base::StringPrintf("location.href = '%s'", url.spec().c_str());
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TestNavigationObserver load_observer(shell()->web_contents(), 1);
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool result = ExecuteScript(window->web_contents(), script);
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_TRUE(result);
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (should_wait_for_navigation)
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      load_observer.Wait();
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Use --site-per-process to force process swaps for cross-site transfers.
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    command_line->AppendSwitch(switches::kSitePerProcess);
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void InjectResourceDisptcherHostDelegate() {
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    old_delegate_ = ResourceDispatcherHostImpl::Get()->delegate();
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ResourceDispatcherHostImpl::Get()->SetDelegate(&tracking_delegate_);
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void RestoreResourceDisptcherHostDelegate() {
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate_);
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    old_delegate_ = NULL;
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TrackingResourceDispatcherHostDelegate& tracking_delegate() {
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return tracking_delegate_;
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TrackingResourceDispatcherHostDelegate tracking_delegate_;
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ResourceDispatcherHostDelegate* old_delegate_;
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The following tests crash in the ThreadSanitizer runtime,
235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// http://crbug.com/356758.
236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(THREAD_SANITIZER)
237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#define MAYBE_ReplaceEntryCrossProcessThenTransfer \
238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DISABLED_ReplaceEntryCrossProcessThenTransfer
239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#define MAYBE_ReplaceEntryCrossProcessTwice \
240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DISABLED_ReplaceEntryCrossProcessTwice
241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#else
242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#define MAYBE_ReplaceEntryCrossProcessThenTransfer \
243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ReplaceEntryCrossProcessThenTransfer
244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#define MAYBE_ReplaceEntryCrossProcessTwice ReplaceEntryCrossProcessTwice
245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Tests that the |should_replace_current_entry| flag persists correctly across
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// request transfers that began with a cross-process navigation.
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       MAYBE_ReplaceEntryCrossProcessThenTransfer) {
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const NavigationController& controller =
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      shell()->web_contents()->GetController();
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host_resolver()->AddRule("*", "127.0.0.1");
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // These must all stay in scope with replace_host.
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL::Replacements replace_host;
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string a_com("A.com");
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string b_com("B.com");
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate to a starting URL, so there is a history entry to replace.
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURL(shell(), url1);
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Force all future navigations to transfer. Note that this includes same-site
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // navigiations which may cause double process swaps (via OpenURL and then via
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // transfer). This test intentionally exercises that case.
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate to a page on A.com with entry replacement. This navigation is
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // cross-site, so the renderer will send it to the browser via OpenURL to give
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to a new process. It will then be transferred into yet another process due
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to the call above.
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  replace_host.SetHostStr(a_com);
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  url2 = url2.ReplaceComponents(replace_host);
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Used to make sure the request for url2 succeeds, and there was only one of
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // them.
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  tracking_delegate().SetTrackedURL(url2);
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURLContentInitiated(shell(), url2, true, true);
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There should be one history entry. url2 should have replaced url1.
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(controller.GetPendingEntry() == NULL);
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, controller.GetEntryCount());
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(0, controller.GetCurrentEntryIndex());
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Make sure the request succeeded.
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted());
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Now navigate as before to a page on B.com, but normally (without
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // replacement). This will still perform a double process-swap as above, via
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // OpenURL and then transfer.
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  replace_host.SetHostStr(b_com);
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  url3 = url3.ReplaceComponents(replace_host);
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Used to make sure the request for url3 succeeds, and there was only one of
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // them.
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  tracking_delegate().SetTrackedURL(url3);
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURLContentInitiated(shell(), url3, false, true);
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There should be two history entries. url2 should have replaced url1. url2
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // should not have replaced url3.
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(controller.GetPendingEntry() == NULL);
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(2, controller.GetEntryCount());
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, controller.GetCurrentEntryIndex());
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL());
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Make sure the request succeeded.
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted());
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Tests that the |should_replace_current_entry| flag persists correctly across
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// request transfers that began with a content-initiated in-process
314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// navigation. This test is the same as the test above, except transfering from
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// in-process.
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       ReplaceEntryInProcessThenTranfers) {
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const NavigationController& controller =
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      shell()->web_contents()->GetController();
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate to a starting URL, so there is a history entry to replace.
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url = test_server()->GetURL("files/site_isolation/blank.html?1");
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURL(shell(), url);
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Force all future navigations to transfer. Note that this includes same-site
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // navigiations which may cause double process swaps (via OpenURL and then via
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // transfer). All navigations in this test are same-site, so it only swaps
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // processes via request transfer.
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate in-process with entry replacement. It will then be transferred
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // into a new one due to the call above.
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURLContentInitiated(shell(), url2, true, true);
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There should be one history entry. url2 should have replaced url1.
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(controller.GetPendingEntry() == NULL);
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, controller.GetEntryCount());
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(0, controller.GetCurrentEntryIndex());
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Now navigate as before, but without replacement.
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURLContentInitiated(shell(), url3, false, true);
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There should be two history entries. url2 should have replaced url1. url2
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // should not have replaced url3.
349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(controller.GetPendingEntry() == NULL);
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(2, controller.GetEntryCount());
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, controller.GetCurrentEntryIndex());
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL());
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Tests that the |should_replace_current_entry| flag persists correctly across
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// request transfers that cross processes twice from renderer policy.
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       MAYBE_ReplaceEntryCrossProcessTwice) {
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const NavigationController& controller =
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      shell()->web_contents()->GetController();
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host_resolver()->AddRule("*", "127.0.0.1");
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // These must all stay in scope with replace_host.
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL::Replacements replace_host;
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string a_com("A.com");
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string b_com("B.com");
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate to a starting URL, so there is a history entry to replace.
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURL(shell(), url1);
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate to a page on A.com which redirects to B.com with entry
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // replacement. This will switch processes via OpenURL twice. First to A.com,
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // and second in response to the server redirect to B.com. The second swap is
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // also renderer-initiated via OpenURL because decidePolicyForNavigation is
378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // currently applied on redirects.
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url2b = test_server()->GetURL("files/site_isolation/blank.html?2");
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  replace_host.SetHostStr(b_com);
381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  url2b = url2b.ReplaceComponents(replace_host);
382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url2a = test_server()->GetURL(
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "server-redirect?" + net::EscapeQueryParamValue(url2b.spec(), false));
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  replace_host.SetHostStr(a_com);
385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  url2a = url2a.ReplaceComponents(replace_host);
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURLContentInitiated(shell(), url2a, true, true);
387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There should be one history entry. url2b should have replaced url1.
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(controller.GetPendingEntry() == NULL);
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, controller.GetEntryCount());
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(0, controller.GetCurrentEntryIndex());
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL());
393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Now repeat without replacement.
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url3b = test_server()->GetURL("files/site_isolation/blank.html?3");
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  replace_host.SetHostStr(b_com);
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  url3b = url3b.ReplaceComponents(replace_host);
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url3a = test_server()->GetURL(
399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "server-redirect?" + net::EscapeQueryParamValue(url3b.spec(), false));
400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  replace_host.SetHostStr(a_com);
401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  url3a = url3a.ReplaceComponents(replace_host);
402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURLContentInitiated(shell(), url3a, false, true);
403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There should be two history entries. url2b should have replaced url1. url2b
405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // should not have replaced url3b.
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(controller.GetPendingEntry() == NULL);
407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(2, controller.GetEntryCount());
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, controller.GetCurrentEntryIndex());
409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL());
410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL());
411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Tests that the request is destroyed when a cross process navigation is
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// cancelled.
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, NoLeakOnCrossSiteCancel) {
416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const NavigationController& controller =
417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      shell()->web_contents()->GetController();
418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host_resolver()->AddRule("*", "127.0.0.1");
419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // These must all stay in scope with replace_host.
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL::Replacements replace_host;
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string a_com("A.com");
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string b_com("B.com");
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate to a starting URL, so there is a history entry to replace.
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURL(shell(), url1);
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Force all future navigations to transfer.
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NoTransferRequestDelegate no_transfer_request_delegate;
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WebContentsDelegate* old_delegate = shell()->web_contents()->GetDelegate();
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  shell()->web_contents()->SetDelegate(&no_transfer_request_delegate);
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Navigate to a page on A.com with entry replacement. This navigation is
438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // cross-site, so the renderer will send it to the browser via OpenURL to give
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to a new process. It will then be transferred into yet another process due
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to the call above.
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  replace_host.SetHostStr(a_com);
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  url2 = url2.ReplaceComponents(replace_host);
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Used to make sure the second request is cancelled, and there is only one
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // request for url2.
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  tracking_delegate().SetTrackedURL(url2);
447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Don't wait for the navigation to complete, since that never happens in
449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // this case.
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NavigateToURLContentInitiated(shell(), url2, false, false);
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There should be one history entry, with url1.
453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, controller.GetEntryCount());
454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(0, controller.GetCurrentEntryIndex());
455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL());
456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Make sure the request for url2 did not complete.
458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(tracking_delegate().WaitForTrackedURLAndGetCompleted());
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  shell()->web_contents()->SetDelegate(old_delegate);
461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace content
464