// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/media/audio_state_provider.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/frame_messages.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/view_messages.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"

namespace content {
namespace {

class TestInterstitialPage;

class TestInterstitialPageDelegate : public InterstitialPageDelegate {
 public:
  explicit TestInterstitialPageDelegate(TestInterstitialPage* interstitial_page)
      : interstitial_page_(interstitial_page) {}
  void CommandReceived(const std::string& command) override;
  std::string GetHTMLContents() override { return std::string(); }
  void OnDontProceed() override;
  void OnProceed() override;

 private:
  TestInterstitialPage* interstitial_page_;
};

class TestInterstitialPage : public InterstitialPageImpl {
 public:
  enum InterstitialState {
    INVALID = 0,    // Hasn't yet been initialized.
    UNDECIDED,      // Initialized, but no decision taken yet.
    OKED,           // Proceed was called.
    CANCELED        // DontProceed was called.
  };

  class Delegate {
   public:
    virtual void TestInterstitialPageDeleted(
        TestInterstitialPage* interstitial) = 0;

   protected:
    virtual ~Delegate() {}
  };

  // IMPORTANT NOTE: if you pass stack allocated values for |state| and
  // |deleted| (like all interstitial related tests do at this point), make sure
  // to create an instance of the TestInterstitialPageStateGuard class on the
  // stack in your test.  This will ensure that the TestInterstitialPage states
  // are cleared when the test finishes.
  // Not doing so will cause stack trashing if your test does not hide the
  // interstitial, as in such a case it will be destroyed in the test TearDown
  // method and will dereference the |deleted| local variable which by then is
  // out of scope.
  TestInterstitialPage(WebContentsImpl* contents,
                       bool new_navigation,
                       const GURL& url,
                       InterstitialState* state,
                       bool* deleted)
      : InterstitialPageImpl(
            contents,
            static_cast<RenderWidgetHostDelegate*>(contents),
            new_navigation, url, new TestInterstitialPageDelegate(this)),
        state_(state),
        deleted_(deleted),
        command_received_count_(0),
        delegate_(nullptr) {
    *state_ = UNDECIDED;
    *deleted_ = false;
  }

  ~TestInterstitialPage() override {
    if (deleted_)
      *deleted_ = true;
    if (delegate_)
      delegate_->TestInterstitialPageDeleted(this);
  }

  void OnDontProceed() {
    if (state_)
      *state_ = CANCELED;
  }
  void OnProceed() {
    if (state_)
      *state_ = OKED;
  }

  int command_received_count() const {
    return command_received_count_;
  }

  void TestDomOperationResponse(const std::string& json_string) {
    if (enabled())
      CommandReceived();
  }

  void TestDidNavigate(int page_id,
                       int nav_entry_id,
                       bool did_create_new_entry,
                       const GURL& url) {
    FrameHostMsg_DidCommitProvisionalLoad_Params params;
    InitNavigateParams(&params, page_id, nav_entry_id, did_create_new_entry,
                       url, ui::PAGE_TRANSITION_TYPED);
    DidNavigate(GetMainFrame()->GetRenderViewHost(), params);
  }

  void TestRenderViewTerminated(base::TerminationStatus status,
                                int error_code) {
    RenderViewTerminated(GetMainFrame()->GetRenderViewHost(), status,
                         error_code);
  }

  bool is_showing() const {
    return static_cast<TestRenderWidgetHostView*>(
               GetMainFrame()->GetRenderViewHost()->GetView())->is_showing();
  }

  void ClearStates() {
    state_ = nullptr;
    deleted_ = nullptr;
    delegate_ = nullptr;
  }

  void CommandReceived() {
    command_received_count_++;
  }

  void set_delegate(Delegate* delegate) {
    delegate_ = delegate;
  }

 protected:
  WebContentsView* CreateWebContentsView() override { return nullptr; }

 private:
  InterstitialState* state_;
  bool* deleted_;
  int command_received_count_;
  Delegate* delegate_;
};

void TestInterstitialPageDelegate::CommandReceived(const std::string& command) {
  interstitial_page_->CommandReceived();
}

void TestInterstitialPageDelegate::OnDontProceed() {
  interstitial_page_->OnDontProceed();
}

void TestInterstitialPageDelegate::OnProceed() {
  interstitial_page_->OnProceed();
}

class TestInterstitialPageStateGuard : public TestInterstitialPage::Delegate {
 public:
  explicit TestInterstitialPageStateGuard(
      TestInterstitialPage* interstitial_page)
      : interstitial_page_(interstitial_page) {
    DCHECK(interstitial_page_);
    interstitial_page_->set_delegate(this);
  }
  ~TestInterstitialPageStateGuard() override {
    if (interstitial_page_)
      interstitial_page_->ClearStates();
  }

  void TestInterstitialPageDeleted(
      TestInterstitialPage* interstitial) override {
    DCHECK(interstitial_page_ == interstitial);
    interstitial_page_ = nullptr;
  }

 private:
  TestInterstitialPage* interstitial_page_;
};

class WebContentsImplTestBrowserClient : public TestContentBrowserClient {
 public:
  WebContentsImplTestBrowserClient()
      : assign_site_for_url_(false) {}

  ~WebContentsImplTestBrowserClient() override {}

  bool ShouldAssignSiteForURL(const GURL& url) override {
    return assign_site_for_url_;
  }

  void set_assign_site_for_url(bool assign) {
    assign_site_for_url_ = assign;
  }

 private:
  bool assign_site_for_url_;
};

class WebContentsImplTest : public RenderViewHostImplTestHarness {
 public:
  void SetUp() override {
    RenderViewHostImplTestHarness::SetUp();
    WebUIControllerFactory::RegisterFactory(
        ContentWebUIControllerFactory::GetInstance());
  }

  void TearDown() override {
    WebUIControllerFactory::UnregisterFactoryForTesting(
        ContentWebUIControllerFactory::GetInstance());
    RenderViewHostImplTestHarness::TearDown();
  }
};

class TestWebContentsObserver : public WebContentsObserver {
 public:
  explicit TestWebContentsObserver(WebContents* contents)
      : WebContentsObserver(contents),
        last_theme_color_(SK_ColorTRANSPARENT) {
  }
  ~TestWebContentsObserver() override {}

  void DidFinishLoad(RenderFrameHost* render_frame_host,
                     const GURL& validated_url) override {
    last_url_ = validated_url;
  }
  void DidFailLoad(RenderFrameHost* render_frame_host,
                   const GURL& validated_url,
                   int error_code,
                   const base::string16& error_description) override {
    last_url_ = validated_url;
  }

  void DidChangeThemeColor(SkColor theme_color) override {
    last_theme_color_ = theme_color;
  }

  const GURL& last_url() const { return last_url_; }
  SkColor last_theme_color() const { return last_theme_color_; }

 private:
  GURL last_url_;
  SkColor last_theme_color_;

  DISALLOW_COPY_AND_ASSIGN(TestWebContentsObserver);
};

// Pretends to be a normal browser that receives toggles and transitions to/from
// a fullscreened state.
class FakeFullscreenDelegate : public WebContentsDelegate {
 public:
  FakeFullscreenDelegate() : fullscreened_contents_(nullptr) {}
  ~FakeFullscreenDelegate() override {}

  void EnterFullscreenModeForTab(WebContents* web_contents,
                                 const GURL& origin) override {
    fullscreened_contents_ = web_contents;
  }

  void ExitFullscreenModeForTab(WebContents* web_contents) override {
    fullscreened_contents_ = nullptr;
  }

  bool IsFullscreenForTabOrPending(
      const WebContents* web_contents) const override {
    return fullscreened_contents_ && web_contents == fullscreened_contents_;
  }

 private:
  WebContents* fullscreened_contents_;

  DISALLOW_COPY_AND_ASSIGN(FakeFullscreenDelegate);
};

class FakeValidationMessageDelegate : public WebContentsDelegate {
 public:
  FakeValidationMessageDelegate()
      : hide_validation_message_was_called_(false) {}
  ~FakeValidationMessageDelegate() override {}

  void HideValidationMessage(WebContents* web_contents) override {
    hide_validation_message_was_called_ = true;
  }

  bool hide_validation_message_was_called() const {
    return hide_validation_message_was_called_;
  }

 private:
  bool hide_validation_message_was_called_;

  DISALLOW_COPY_AND_ASSIGN(FakeValidationMessageDelegate);
};

}  // namespace

// Test to make sure that title updates get stripped of whitespace.
TEST_F(WebContentsImplTest, UpdateTitle) {
  NavigationControllerImpl& cont =
      static_cast<NavigationControllerImpl&>(controller());
  FrameHostMsg_DidCommitProvisionalLoad_Params params;
  InitNavigateParams(&params, 0, 0, true, GURL(url::kAboutBlankURL),
                     ui::PAGE_TRANSITION_TYPED);

  LoadCommittedDetails details;
  cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details);

  contents()->UpdateTitle(contents()->GetMainFrame(), 0,
                          base::ASCIIToUTF16("    Lots O' Whitespace\n"),
                          base::i18n::LEFT_TO_RIGHT);
  EXPECT_EQ(base::ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle());
}

TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) {
  const GURL kGURL("chrome://blah");
  controller().LoadURL(
      kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  EXPECT_EQ(base::string16(), contents()->GetTitle());
}

TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) {
  const GURL kGURL("chrome://blah");
  const base::string16 title = base::ASCIIToUTF16("My Title");
  controller().LoadURL(
      kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());

  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_EQ(kGURL, entry->GetURL());
  entry->SetTitle(title);

  EXPECT_EQ(title, contents()->GetTitle());
}

// Test view source mode for a webui page.
TEST_F(WebContentsImplTest, NTPViewSource) {
  NavigationControllerImpl& cont =
      static_cast<NavigationControllerImpl&>(controller());
  const char kUrl[] = "view-source:chrome://blah";
  const GURL kGURL(kUrl);

  process()->sink().ClearMessages();

  cont.LoadURL(
      kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = cont.GetPendingEntry()->GetUniqueID();
  rvh()->GetDelegate()->RenderViewCreated(rvh());
  // Did we get the expected message?
  EXPECT_TRUE(process()->sink().GetFirstMessageMatching(
      ViewMsg_EnableViewSourceMode::ID));

  FrameHostMsg_DidCommitProvisionalLoad_Params params;
  InitNavigateParams(&params, 0, entry_id, true, kGURL,
                     ui::PAGE_TRANSITION_TYPED);
  LoadCommittedDetails details;
  cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details);
  // Also check title and url.
  EXPECT_EQ(base::ASCIIToUTF16(kUrl), contents()->GetTitle());
}

// Test to ensure UpdateMaxPageID is working properly.
TEST_F(WebContentsImplTest, UpdateMaxPageID) {
  SiteInstance* instance1 = contents()->GetSiteInstance();
  scoped_refptr<SiteInstance> instance2(SiteInstance::Create(nullptr));

  // Starts at -1.
  EXPECT_EQ(-1, contents()->GetMaxPageID());
  EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance1));
  EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance2.get()));

  // Make sure max_page_id_ is monotonically increasing per SiteInstance.
  contents()->UpdateMaxPageID(3);
  contents()->UpdateMaxPageID(1);
  EXPECT_EQ(3, contents()->GetMaxPageID());
  EXPECT_EQ(3, contents()->GetMaxPageIDForSiteInstance(instance1));
  EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance2.get()));

  contents()->UpdateMaxPageIDForSiteInstance(instance2.get(), 7);
  EXPECT_EQ(3, contents()->GetMaxPageID());
  EXPECT_EQ(3, contents()->GetMaxPageIDForSiteInstance(instance1));
  EXPECT_EQ(7, contents()->GetMaxPageIDForSiteInstance(instance2.get()));
}

// Test simple same-SiteInstance navigation.
TEST_F(WebContentsImplTest, SimpleNavigation) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  SiteInstance* instance1 = contents()->GetSiteInstance();
  EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());

  // Navigate to URL
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  main_test_rfh()->PrepareForCommit();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
  // Controller's pending entry will have a null site instance until we assign
  // it in DidNavigate.
  EXPECT_EQ(
      nullptr,
      NavigationEntryImpl::FromNavigationEntry(controller().GetVisibleEntry())->
          site_instance());

  // DidNavigate from the page
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
  EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
  // Controller's entry should now have the SiteInstance, or else we won't be
  // able to find it later.
  EXPECT_EQ(
      instance1,
      NavigationEntryImpl::FromNavigationEntry(controller().GetVisibleEntry())->
          site_instance());
}

// Test that we reject NavigateToEntry if the url is over kMaxURLChars.
TEST_F(WebContentsImplTest, NavigateToExcessivelyLongURL) {
  // Construct a URL that's kMaxURLChars + 1 long of all 'a's.
  const GURL url(std::string("http://example.org/").append(
      GetMaxURLChars() + 1, 'a'));

  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_GENERATED, std::string());
  EXPECT_EQ(nullptr, controller().GetVisibleEntry());
}

// Test that navigating across a site boundary creates a new RenderViewHost
// with a new SiteInstance.  Going back should do the same.
TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
  bool is_site_per_process = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kSitePerProcess);
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  int orig_rvh_delete_count = 0;
  orig_rfh->GetRenderViewHost()->set_delete_counter(&orig_rvh_delete_count);
  SiteInstance* instance1 = contents()->GetSiteInstance();

  // Navigate to URL.  First URL should use first RenderViewHost.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);

  // Keep the number of active frames in orig_rfh's SiteInstance non-zero so
  // that orig_rfh doesn't get deleted when it gets swapped out.
  orig_rfh->GetSiteInstance()->increment_active_frame_count();

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh->GetRenderViewHost(), contents()->GetRenderViewHost());
  EXPECT_EQ(url, contents()->GetLastCommittedURL());
  EXPECT_EQ(url, contents()->GetVisibleURL());

  // Navigate to new site
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableBrowserSideNavigation)) {
    orig_rfh->PrepareForCommit();
  }
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(url, contents()->GetLastCommittedURL());
  EXPECT_EQ(url2, contents()->GetVisibleURL());
  TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
  int pending_rvh_delete_count = 0;
  pending_rfh->GetRenderViewHost()->set_delete_counter(
      &pending_rvh_delete_count);

  // Navigations should be suspended in pending_rfh until BeforeUnloadACK.
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableBrowserSideNavigation)) {
    EXPECT_TRUE(pending_rfh->are_navigations_suspended());
    orig_rfh->SendBeforeUnloadACK(true);
    EXPECT_FALSE(pending_rfh->are_navigations_suspended());
  }

  // DidNavigate from the pending page
  contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance2 = contents()->GetSiteInstance();

  // Keep the number of active frames in pending_rfh's SiteInstance
  // non-zero so that orig_rfh doesn't get deleted when it gets
  // swapped out.
  pending_rfh->GetSiteInstance()->increment_active_frame_count();

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
  EXPECT_EQ(url2, contents()->GetLastCommittedURL());
  EXPECT_EQ(url2, contents()->GetVisibleURL());
  EXPECT_NE(instance1, instance2);
  EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
  // We keep a proxy for the original RFH's SiteInstance.
  EXPECT_TRUE(contents()->GetRenderManagerForTesting()->GetRenderFrameProxyHost(
      orig_rfh->GetSiteInstance()));
  EXPECT_EQ(orig_rvh_delete_count, 0);

  // Going back should switch SiteInstances again.  The first SiteInstance is
  // stored in the NavigationEntry, so it should be the same as at the start.
  // We should use the same RFH as before, swapping it back in.
  controller().GoBack();
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableBrowserSideNavigation)) {
    contents()->GetMainFrame()->PrepareForCommit();
  }
  TestRenderFrameHost* goback_rfh = contents()->GetPendingMainFrame();
  if (!is_site_per_process)
    EXPECT_EQ(orig_rfh, goback_rfh);
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());

  // Navigations should be suspended in goback_rfh until BeforeUnloadACK.
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableBrowserSideNavigation)) {
    EXPECT_TRUE(goback_rfh->are_navigations_suspended());
    pending_rfh->SendBeforeUnloadACK(true);
    EXPECT_FALSE(goback_rfh->are_navigations_suspended());
  }

  // DidNavigate from the back action
  contents()->TestDidNavigate(goback_rfh, 1, entry_id, false, url2,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(goback_rfh, contents()->GetMainFrame());
  EXPECT_EQ(instance1, contents()->GetSiteInstance());
  // There should be a proxy for the pending RFH SiteInstance.
  EXPECT_TRUE(contents()->GetRenderManagerForTesting()->
      GetRenderFrameProxyHost(pending_rfh->GetSiteInstance()));
  EXPECT_EQ(pending_rvh_delete_count, 0);
  pending_rfh->OnSwappedOut();

  // Close contents and ensure RVHs are deleted.
  DeleteContents();
  EXPECT_EQ(orig_rvh_delete_count, 1);
  EXPECT_EQ(pending_rvh_delete_count, 1);
}

// Test that navigating across a site boundary after a crash creates a new
// RFH without requiring a cross-site transition (i.e., PENDING state).
TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  int orig_rvh_delete_count = 0;
  orig_rfh->GetRenderViewHost()->set_delete_counter(&orig_rvh_delete_count);
  SiteInstance* instance1 = contents()->GetSiteInstance();

  // Navigate to URL.  First URL should use first RenderViewHost.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh->GetRenderViewHost(), contents()->GetRenderViewHost());

  // Simulate a renderer crash.
  EXPECT_TRUE(orig_rfh->IsRenderFrameLive());
  orig_rfh->GetProcess()->SimulateCrash();
  EXPECT_FALSE(orig_rfh->IsRenderFrameLive());

  // Navigate to new site.  We should not go into PENDING.
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  TestRenderFrameHost* new_rfh = contents()->GetMainFrame();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
  EXPECT_NE(orig_rfh, new_rfh);
  EXPECT_EQ(orig_rvh_delete_count, 1);

  // DidNavigate from the new page
  contents()->TestDidNavigate(new_rfh, 1, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance2 = contents()->GetSiteInstance();

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(new_rfh, main_rfh());
  EXPECT_NE(instance1, instance2);
  EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());

  // Close contents and ensure RVHs are deleted.
  DeleteContents();
  EXPECT_EQ(orig_rvh_delete_count, 1);
}

// Test that opening a new contents in the same SiteInstance and then navigating
// both contentses to a new site will place both contentses in a single
// SiteInstance.
TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  SiteInstance* instance1 = contents()->GetSiteInstance();

  // Navigate to URL.  First URL should use first RenderViewHost.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);

  // Open a new contents with the same SiteInstance, navigated to the same site.
  scoped_ptr<TestWebContents> contents2(
      TestWebContents::Create(browser_context(), instance1));
  contents2->GetController().LoadURL(url, Referrer(),
                                     ui::PAGE_TRANSITION_TYPED,
                                     std::string());
  entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
  contents2->GetMainFrame()->PrepareForCommit();
  // Need this page id to be 2 since the site instance is the same (which is the
  // scope of page IDs) and we want to consider this a new page.
  contents2->TestDidNavigate(contents2->GetMainFrame(), 2, entry_id, true, url,
                             ui::PAGE_TRANSITION_TYPED);

  // Navigate first contents to a new site.
  const GURL url2a("http://www.yahoo.com");
  controller().LoadURL(
      url2a, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  orig_rfh->PrepareForCommit();
  TestRenderFrameHost* pending_rfh_a = contents()->GetPendingMainFrame();
  contents()->TestDidNavigate(pending_rfh_a, 1, entry_id, true, url2a,
                              ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance2a = contents()->GetSiteInstance();
  EXPECT_NE(instance1, instance2a);

  // Navigate second contents to the same site as the first tab.
  const GURL url2b("http://mail.yahoo.com");
  contents2->GetController().LoadURL(url2b, Referrer(),
                                     ui::PAGE_TRANSITION_TYPED,
                                     std::string());
  entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
  TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
  rfh2->PrepareForCommit();
  TestRenderFrameHost* pending_rfh_b = contents2->GetPendingMainFrame();
  EXPECT_NE(nullptr, pending_rfh_b);
  EXPECT_TRUE(contents2->CrossProcessNavigationPending());

  // NOTE(creis): We used to be in danger of showing a crash page here if the
  // second contents hadn't navigated somewhere first (bug 1145430).  That case
  // is now covered by the CrossSiteBoundariesAfterCrash test.
  contents2->TestDidNavigate(pending_rfh_b, 2, entry_id, true, url2b,
                             ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance2b = contents2->GetSiteInstance();
  EXPECT_NE(instance1, instance2b);

  // Both contentses should now be in the same SiteInstance.
  EXPECT_EQ(instance2a, instance2b);
}

// The embedder can request sites for certain urls not be be assigned to the
// SiteInstance through ShouldAssignSiteForURL() in content browser client,
// allowing to reuse the renderer backing certain chrome urls for subsequent
// navigation. The test verifies that the override is honored.
TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
  WebContentsImplTestBrowserClient browser_client;
  SetBrowserClientForTesting(&browser_client);

  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  int orig_rvh_delete_count = 0;
  orig_rfh->GetRenderViewHost()->set_delete_counter(&orig_rvh_delete_count);
  SiteInstanceImpl* orig_instance = contents()->GetSiteInstance();

  browser_client.set_assign_site_for_url(false);
  // Navigate to an URL that will not assign a new SiteInstance.
  const GURL native_url("non-site-url://stuffandthings");
  controller().LoadURL(
      native_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, native_url,
                              ui::PAGE_TRANSITION_TYPED);

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
  EXPECT_EQ(native_url, contents()->GetLastCommittedURL());
  EXPECT_EQ(native_url, contents()->GetVisibleURL());
  EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
  EXPECT_EQ(GURL(), contents()->GetSiteInstance()->GetSiteURL());
  EXPECT_FALSE(orig_instance->HasSite());

  browser_client.set_assign_site_for_url(true);
  // Navigate to new site (should keep same site instance).
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(native_url, contents()->GetLastCommittedURL());
  EXPECT_EQ(url, contents()->GetVisibleURL());
  EXPECT_FALSE(contents()->GetPendingMainFrame());
  contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);

  // Keep the number of active frames in orig_rfh's SiteInstance
  // non-zero so that orig_rfh doesn't get deleted when it gets
  // swapped out.
  orig_rfh->GetSiteInstance()->increment_active_frame_count();

  EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
  EXPECT_TRUE(
      contents()->GetSiteInstance()->GetSiteURL().DomainIs("google.com"));
  EXPECT_EQ(url, contents()->GetLastCommittedURL());

  // Navigate to another new site (should create a new site instance).
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableBrowserSideNavigation)) {
    orig_rfh->PrepareForCommit();
  }
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(url, contents()->GetLastCommittedURL());
  EXPECT_EQ(url2, contents()->GetVisibleURL());
  TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
  int pending_rvh_delete_count = 0;
  pending_rfh->GetRenderViewHost()->set_delete_counter(
      &pending_rvh_delete_count);

  // Navigations should be suspended in pending_rvh until BeforeUnloadACK.
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableBrowserSideNavigation)) {
    EXPECT_TRUE(pending_rfh->are_navigations_suspended());
    orig_rfh->SendBeforeUnloadACK(true);
    EXPECT_FALSE(pending_rfh->are_navigations_suspended());
  }

  // DidNavigate from the pending page.
  contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  SiteInstance* new_instance = contents()->GetSiteInstance();

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
  EXPECT_EQ(url2, contents()->GetLastCommittedURL());
  EXPECT_EQ(url2, contents()->GetVisibleURL());
  EXPECT_NE(new_instance, orig_instance);
  EXPECT_FALSE(contents()->GetPendingMainFrame());
  // We keep a proxy for the original RFH's SiteInstance.
  EXPECT_TRUE(contents()->GetRenderManagerForTesting()->GetRenderFrameProxyHost(
      orig_rfh->GetSiteInstance()));
  EXPECT_EQ(orig_rvh_delete_count, 0);
  orig_rfh->OnSwappedOut();

  // Close contents and ensure RVHs are deleted.
  DeleteContents();
  EXPECT_EQ(orig_rvh_delete_count, 1);
  EXPECT_EQ(pending_rvh_delete_count, 1);
}

// Regression test for http://crbug.com/386542 - variation of
// NavigateFromSitelessUrl in which the original navigation is a session
// restore.
TEST_F(WebContentsImplTest, NavigateFromRestoredSitelessUrl) {
  WebContentsImplTestBrowserClient browser_client;
  SetBrowserClientForTesting(&browser_client);
  SiteInstanceImpl* orig_instance = contents()->GetSiteInstance();
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  // Restore a navigation entry for URL that should not assign site to the
  // SiteInstance.
  browser_client.set_assign_site_for_url(false);
  const GURL native_url("non-site-url://stuffandthings");
  std::vector<NavigationEntry*> entries;
  NavigationEntry* entry = NavigationControllerImpl::CreateNavigationEntry(
      native_url, Referrer(), ui::PAGE_TRANSITION_LINK, false, std::string(),
      browser_context());
  entry->SetPageID(0);
  entries.push_back(entry);
  controller().Restore(
      0,
      NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY,
      &entries);
  ASSERT_EQ(0u, entries.size());
  ASSERT_EQ(1, controller().GetEntryCount());
  controller().GoToIndex(0);
  entry = controller().GetPendingEntry();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 0, entry->GetUniqueID(), false,
                              native_url, ui::PAGE_TRANSITION_RELOAD);
  EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
  EXPECT_EQ(GURL(), contents()->GetSiteInstance()->GetSiteURL());
  EXPECT_FALSE(orig_instance->HasSite());

  // Navigate to a regular site and verify that the SiteInstance was kept.
  browser_client.set_assign_site_for_url(true);
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry = controller().GetPendingEntry();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 2, entry->GetUniqueID(), true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_EQ(orig_instance, contents()->GetSiteInstance());

  // Cleanup.
  DeleteContents();
}

// Complement for NavigateFromRestoredSitelessUrl, verifying that when a regular
// tab is restored, the SiteInstance will change upon navigation.
TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
  WebContentsImplTestBrowserClient browser_client;
  SetBrowserClientForTesting(&browser_client);
  SiteInstanceImpl* orig_instance = contents()->GetSiteInstance();
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  // Restore a navigation entry for a regular URL ensuring that the embedder
  // ShouldAssignSiteForUrl override is disabled (i.e. returns true).
  browser_client.set_assign_site_for_url(true);
  const GURL regular_url("http://www.yahoo.com");
  std::vector<NavigationEntry*> entries;
  NavigationEntry* entry = NavigationControllerImpl::CreateNavigationEntry(
      regular_url, Referrer(), ui::PAGE_TRANSITION_LINK, false, std::string(),
      browser_context());
  entry->SetPageID(0);
  entries.push_back(entry);
  controller().Restore(
      0,
      NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY,
      &entries);
  ASSERT_EQ(0u, entries.size());
  ASSERT_EQ(1, controller().GetEntryCount());
  controller().GoToIndex(0);
  entry = controller().GetPendingEntry();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 0, entry->GetUniqueID(), false,
                              regular_url, ui::PAGE_TRANSITION_RELOAD);
  EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
  EXPECT_TRUE(orig_instance->HasSite());

  // Navigate to another site and verify that a new SiteInstance was created.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry = controller().GetPendingEntry();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(contents()->GetPendingMainFrame(), 2,
                              entry->GetUniqueID(), true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_NE(orig_instance, contents()->GetSiteInstance());

  // Cleanup.
  DeleteContents();
}

// Test that we can find an opener RVH even if it's pending.
// http://crbug.com/176252.
TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  // Navigate to a URL.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);

  // Start to navigate first tab to a new site, so that it has a pending RVH.
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  orig_rfh->PrepareForCommit();
  TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();

  // While it is still pending, simulate opening a new tab with the first tab
  // as its opener.  This will call WebContentsImpl::CreateOpenerRenderViews
  // on the opener to ensure that an RVH exists.
  int opener_routing_id =
      contents()->CreateOpenerRenderViews(pending_rfh->GetSiteInstance());

  // We should find the pending RVH and not create a new one.
  EXPECT_EQ(pending_rfh->GetRenderViewHost()->GetRoutingID(),
            opener_routing_id);
}

// Tests that WebContentsImpl uses the current URL, not the SiteInstance's site,
// to determine whether a navigation is cross-site.
TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  SiteInstance* instance1 = contents()->GetSiteInstance();

  // Navigate to URL.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);

  // Open a related contents to a second site.
  scoped_ptr<TestWebContents> contents2(
      TestWebContents::Create(browser_context(), instance1));
  const GURL url2("http://www.yahoo.com");
  contents2->GetController().LoadURL(url2, Referrer(),
                                     ui::PAGE_TRANSITION_TYPED,
                                     std::string());
  entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
  contents2->GetMainFrame()->PrepareForCommit();

  // The first RVH in contents2 isn't live yet, so we shortcut the cross site
  // pending.
  TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
  EXPECT_FALSE(contents2->CrossProcessNavigationPending());
  contents2->TestDidNavigate(rfh2, 2, entry_id, true, url2,
                             ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance2 = contents2->GetSiteInstance();
  EXPECT_NE(instance1, instance2);
  EXPECT_FALSE(contents2->CrossProcessNavigationPending());

  // Simulate a link click in first contents to second site.  Doesn't switch
  // SiteInstances, because we don't intercept Blink navigations.
  orig_rfh->SendRendererInitiatedNavigationRequest(url2, true);
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 2, 0, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance3 = contents()->GetSiteInstance();
  EXPECT_EQ(instance1, instance3);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());

  // Navigate to the new site.  Doesn't switch SiteInstancees, because we
  // compare against the current URL, not the SiteInstance's site.
  const GURL url3("http://mail.yahoo.com");
  controller().LoadURL(
      url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 3, entry_id, true, url3,
                              ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance4 = contents()->GetSiteInstance();
  EXPECT_EQ(instance1, instance4);
}

// Test that the onbeforeunload and onunload handlers run when navigating
// across site boundaries.
TEST_F(WebContentsImplTest, CrossSiteUnloadHandlers) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  SiteInstance* instance1 = contents()->GetSiteInstance();

  // Navigate to URL.  First URL should use first RenderViewHost.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());

  // Navigate to new site, but simulate an onbeforeunload denial.
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK());
  base::TimeTicks now = base::TimeTicks::Now();
  orig_rfh->OnMessageReceived(
      FrameHostMsg_BeforeUnload_ACK(0, false, now, now));
  EXPECT_FALSE(orig_rfh->IsWaitingForBeforeUnloadACK());
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());

  // Navigate again, but simulate an onbeforeunload approval.
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK());
  now = base::TimeTicks::Now();
  orig_rfh->PrepareForCommit();
  EXPECT_FALSE(orig_rfh->IsWaitingForBeforeUnloadACK());
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();

  // We won't hear DidNavigate until the onunload handler has finished running.

  // DidNavigate from the pending page.
  contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  SiteInstance* instance2 = contents()->GetSiteInstance();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
  EXPECT_NE(instance1, instance2);
  EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
}

// Test that during a slow cross-site navigation, the original renderer can
// navigate to a different URL and have it displayed, canceling the slow
// navigation.
TEST_F(WebContentsImplTest, CrossSiteNavigationPreempted) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  SiteInstance* instance1 = contents()->GetSiteInstance();

  // Navigate to URL.  First URL should use first RenderFrameHost.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());

  // Navigate to new site, simulating an onbeforeunload approval.
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK());
  orig_rfh->PrepareForCommit();
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());

  // Suppose the original renderer navigates before the new one is ready.
  orig_rfh->SendNavigate(2, 0, true, GURL("http://www.google.com/foo"));

  // Verify that the pending navigation is cancelled.
  EXPECT_FALSE(orig_rfh->IsWaitingForBeforeUnloadACK());
  SiteInstance* instance2 = contents()->GetSiteInstance();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
  EXPECT_EQ(instance1, instance2);
  EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
}

TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
  // Start with a web ui page, which gets a new RVH with WebUI bindings.
  const GURL url1("chrome://gpu");
  controller().LoadURL(
      url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  TestRenderFrameHost* ntp_rfh = contents()->GetMainFrame();
  ntp_rfh->PrepareForCommit();
  contents()->TestDidNavigate(ntp_rfh, 1, entry_id, true, url1,
                              ui::PAGE_TRANSITION_TYPED);
  NavigationEntry* entry1 = controller().GetLastCommittedEntry();
  SiteInstance* instance1 = contents()->GetSiteInstance();

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(ntp_rfh, contents()->GetMainFrame());
  EXPECT_EQ(url1, entry1->GetURL());
  EXPECT_EQ(instance1,
            NavigationEntryImpl::FromNavigationEntry(entry1)->site_instance());
  EXPECT_TRUE(ntp_rfh->GetRenderViewHost()->GetEnabledBindings() &
              BINDINGS_POLICY_WEB_UI);

  // Navigate to new site.
  const GURL url2("http://www.google.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  TestRenderFrameHost* google_rfh = contents()->GetPendingMainFrame();

  // Simulate beforeunload approval.
  EXPECT_TRUE(ntp_rfh->IsWaitingForBeforeUnloadACK());
  base::TimeTicks now = base::TimeTicks::Now();
  ntp_rfh->PrepareForCommit();

  // DidNavigate from the pending page.
  contents()->TestDidNavigate(google_rfh, 1, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  NavigationEntry* entry2 = controller().GetLastCommittedEntry();
  SiteInstance* instance2 = contents()->GetSiteInstance();

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(google_rfh, contents()->GetMainFrame());
  EXPECT_NE(instance1, instance2);
  EXPECT_FALSE(contents()->GetPendingMainFrame());
  EXPECT_EQ(url2, entry2->GetURL());
  EXPECT_EQ(instance2,
            NavigationEntryImpl::FromNavigationEntry(entry2)->site_instance());
  EXPECT_FALSE(google_rfh->GetRenderViewHost()->GetEnabledBindings() &
               BINDINGS_POLICY_WEB_UI);

  // Navigate to third page on same site.
  const GURL url3("http://news.google.com");
  controller().LoadURL(
      url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(google_rfh, 2, entry_id, true, url3,
                              ui::PAGE_TRANSITION_TYPED);
  NavigationEntry* entry3 = controller().GetLastCommittedEntry();
  SiteInstance* instance3 = contents()->GetSiteInstance();

  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(google_rfh, contents()->GetMainFrame());
  EXPECT_EQ(instance2, instance3);
  EXPECT_FALSE(contents()->GetPendingMainFrame());
  EXPECT_EQ(url3, entry3->GetURL());
  EXPECT_EQ(instance3,
            NavigationEntryImpl::FromNavigationEntry(entry3)->site_instance());

  // Go back within the site.
  controller().GoBack();
  NavigationEntry* goback_entry = controller().GetPendingEntry();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(entry2, controller().GetPendingEntry());

  // Before that commits, go back again.
  controller().GoBack();
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  EXPECT_TRUE(contents()->GetPendingMainFrame());
  EXPECT_EQ(entry1, controller().GetPendingEntry());

  // Simulate beforeunload approval.
  EXPECT_TRUE(google_rfh->IsWaitingForBeforeUnloadACK());
  now = base::TimeTicks::Now();
  google_rfh->PrepareForCommit();
  google_rfh->OnMessageReceived(
      FrameHostMsg_BeforeUnload_ACK(0, true, now, now));

  // DidNavigate from the first back. This aborts the second back's pending RFH.
  contents()->TestDidNavigate(google_rfh, 1, goback_entry->GetUniqueID(), false,
                              url2, ui::PAGE_TRANSITION_TYPED);

  // We should commit this page and forget about the second back.
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_FALSE(controller().GetPendingEntry());
  EXPECT_EQ(google_rfh, contents()->GetMainFrame());
  EXPECT_EQ(url2, controller().GetLastCommittedEntry()->GetURL());

  // We should not have corrupted the NTP entry.
  EXPECT_EQ(instance3,
            NavigationEntryImpl::FromNavigationEntry(entry3)->site_instance());
  EXPECT_EQ(instance2,
            NavigationEntryImpl::FromNavigationEntry(entry2)->site_instance());
  EXPECT_EQ(instance1,
            NavigationEntryImpl::FromNavigationEntry(entry1)->site_instance());
  EXPECT_EQ(url1, entry1->GetURL());
}

// Test that during a slow cross-site navigation, a sub-frame navigation in the
// original renderer will not cancel the slow navigation (bug 42029).
TEST_F(WebContentsImplTest, CrossSiteNavigationNotPreemptedByFrame) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  // Navigate to URL.  First URL should use the original RenderFrameHost.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());

  // Start navigating to new site.
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());

  // Simulate a sub-frame navigation arriving and ensure the RVH is still
  // waiting for a before unload response.
  TestRenderFrameHost* child_rfh = orig_rfh->AppendChild("subframe");
  child_rfh->SendNavigateWithTransition(1, 0, false,
                                        GURL("http://google.com/frame"),
                                        ui::PAGE_TRANSITION_AUTO_SUBFRAME);
  EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK());

  // Now simulate the onbeforeunload approval and verify the navigation is
  // not canceled.
  orig_rfh->PrepareForCommit();
  EXPECT_FALSE(orig_rfh->IsWaitingForBeforeUnloadACK());
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
}

// Test that a cross-site navigation is not preempted if the previous
// renderer sends a FrameNavigate message just before being told to stop.
// We should only preempt the cross-site navigation if the previous renderer
// has started a new navigation.  See http://crbug.com/79176.
TEST_F(WebContentsImplTest, CrossSiteNotPreemptedDuringBeforeUnload) {
  // Navigate to WebUI URL.
  const GURL url("chrome://gpu");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry1_id = controller().GetPendingEntry()->GetUniqueID();
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());

  // Navigate to new site, with the beforeunload request in flight.
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry2_id = controller().GetPendingEntry()->GetUniqueID();
  TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK());

  // Suppose the first navigation tries to commit now, with a
  // FrameMsg_Stop in flight.  This should not cancel the pending navigation,
  // but it should act as if the beforeunload ack arrived.
  orig_rfh->SendNavigate(1, entry1_id, true, GURL("chrome://gpu"));
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
  EXPECT_FALSE(orig_rfh->IsWaitingForBeforeUnloadACK());

  // The pending navigation should be able to commit successfully.
  contents()->TestDidNavigate(pending_rfh, 1, entry2_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
}

// Test that NavigationEntries have the correct page state after going
// forward and back.  Prevents regression for bug 1116137.
TEST_F(WebContentsImplTest, NavigationEntryContentState) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  // Navigate to URL.  There should be no committed entry yet.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  NavigationEntry* entry = controller().GetLastCommittedEntry();
  EXPECT_EQ(nullptr, entry);

  // Committed entry should have page state after DidNavigate.
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);
  entry = controller().GetLastCommittedEntry();
  EXPECT_TRUE(entry->GetPageState().IsValid());

  // Navigate to same site.
  const GURL url2("http://images.google.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  entry = controller().GetLastCommittedEntry();
  EXPECT_TRUE(entry->GetPageState().IsValid());

  // Committed entry should have page state after DidNavigate.
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  entry = controller().GetLastCommittedEntry();
  EXPECT_TRUE(entry->GetPageState().IsValid());

  // Now go back.  Committed entry should still have page state.
  controller().GoBack();
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, false, url,
                              ui::PAGE_TRANSITION_TYPED);
  entry = controller().GetLastCommittedEntry();
  EXPECT_TRUE(entry->GetPageState().IsValid());
}

// Test that NavigationEntries have the correct page state and SiteInstance
// state after opening a new window to about:blank.  Prevents regression for
// bugs b/1116137 and http://crbug.com/111975.
TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  // Navigate to about:blank.
  const GURL url(url::kAboutBlankURL);
  orig_rfh->SendRendererInitiatedNavigationRequest(url, false);
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, 0, true, url,
                              ui::PAGE_TRANSITION_TYPED);

  // Should have a page state here.
  NavigationEntry* entry = controller().GetLastCommittedEntry();
  EXPECT_TRUE(entry->GetPageState().IsValid());

  // The SiteInstance should be available for other navigations to use.
  NavigationEntryImpl* entry_impl =
      NavigationEntryImpl::FromNavigationEntry(entry);
  EXPECT_FALSE(entry_impl->site_instance()->HasSite());
  int32 site_instance_id = entry_impl->site_instance()->GetId();

  // Navigating to a normal page should not cause a process swap.
  const GURL new_url("http://www.google.com");
  controller().LoadURL(new_url, Referrer(),
                       ui::PAGE_TRANSITION_TYPED, std::string());
  entry = controller().GetPendingEntry();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 2, entry->GetUniqueID(), true, new_url,
                              ui::PAGE_TRANSITION_TYPED);
  NavigationEntryImpl* entry_impl2 = NavigationEntryImpl::FromNavigationEntry(
      controller().GetLastCommittedEntry());
  EXPECT_EQ(site_instance_id, entry_impl2->site_instance()->GetId());
  EXPECT_TRUE(entry_impl2->site_instance()->HasSite());
}

// Tests that fullscreen is exited throughout the object hierarchy when
// navigating to a new page.
TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
  FakeFullscreenDelegate fake_delegate;
  contents()->SetDelegate(&fake_delegate);
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
  TestRenderViewHost* orig_rvh = orig_rfh->GetRenderViewHost();

  // Navigate to a site.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());

  // Toggle fullscreen mode on (as if initiated via IPC from renderer).
  EXPECT_FALSE(orig_rvh->IsFullscreenGranted());
  EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
  EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
  orig_rfh->OnMessageReceived(
      FrameHostMsg_ToggleFullscreen(orig_rfh->GetRoutingID(), true));
  EXPECT_TRUE(orig_rvh->IsFullscreenGranted());
  EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
  EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));

  // Navigate to a new site.
  const GURL url2("http://www.yahoo.com");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  contents()->GetMainFrame()->PrepareForCommit();
  TestRenderFrameHost* const pending_rfh = contents()->GetPendingMainFrame();
  contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);

  // Confirm fullscreen has exited.
  EXPECT_FALSE(orig_rvh->IsFullscreenGranted());
  EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
  EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));

  contents()->SetDelegate(nullptr);
}

// Tests that fullscreen is exited throughout the object hierarchy when
// instructing NavigationController to GoBack() or GoForward().
TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
  FakeFullscreenDelegate fake_delegate;
  contents()->SetDelegate(&fake_delegate);
  TestRenderFrameHost* const orig_rfh = contents()->GetMainFrame();
  TestRenderViewHost* const orig_rvh = orig_rfh->GetRenderViewHost();

  // Navigate to a site.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  orig_rfh->PrepareForCommit();
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());

  // Now, navigate to another page on the same site.
  const GURL url2("http://www.google.com/search?q=kittens");
  controller().LoadURL(
      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  entry_id = controller().GetPendingEntry()->GetUniqueID();
  orig_rfh->PrepareForCommit();
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url2,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());

  // Sanity-check: Confirm we're not starting out in fullscreen mode.
  EXPECT_FALSE(orig_rvh->IsFullscreenGranted());
  EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
  EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));

  for (int i = 0; i < 2; ++i) {
    // Toggle fullscreen mode on (as if initiated via IPC from renderer).
    orig_rfh->OnMessageReceived(
        FrameHostMsg_ToggleFullscreen(orig_rfh->GetRoutingID(), true));
    EXPECT_TRUE(orig_rvh->IsFullscreenGranted());
    EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
    EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));

    // Navigate backward (or forward).
    if (i == 0)
      controller().GoBack();
    else
      controller().GoForward();
    entry_id = controller().GetPendingEntry()->GetUniqueID();
    orig_rfh->PrepareForCommit();
    EXPECT_FALSE(contents()->CrossProcessNavigationPending());
    EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
    contents()->TestDidNavigate(orig_rfh, i + 1, entry_id, false, url,
                                ui::PAGE_TRANSITION_FORWARD_BACK);

    // Confirm fullscreen has exited.
    EXPECT_FALSE(orig_rvh->IsFullscreenGranted());
    EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
    EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
  }

  contents()->SetDelegate(nullptr);
}

TEST_F(WebContentsImplTest, TerminateHidesValidationMessage) {
  FakeValidationMessageDelegate fake_delegate;
  contents()->SetDelegate(&fake_delegate);
  EXPECT_FALSE(fake_delegate.hide_validation_message_was_called());

  // Initialize the RenderFrame and then simulate crashing the renderer
  // process.
  contents()->GetMainFrame()->InitializeRenderFrameIfNeeded();
  contents()->GetMainFrame()->GetProcess()->SimulateCrash();

  // Confirm HideValidationMessage was called.
  EXPECT_TRUE(fake_delegate.hide_validation_message_was_called());

  contents()->SetDelegate(nullptr);
}

// Tests that fullscreen is exited throughout the object hierarchy on a renderer
// crash.
TEST_F(WebContentsImplTest, CrashExitsFullscreen) {
  FakeFullscreenDelegate fake_delegate;
  contents()->SetDelegate(&fake_delegate);

  // Navigate to a site.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  main_test_rfh()->PrepareForCommit();
  contents()->TestDidNavigate(contents()->GetMainFrame(), 1, entry_id, true,
                              url, ui::PAGE_TRANSITION_TYPED);

  // Toggle fullscreen mode on (as if initiated via IPC from renderer).
  EXPECT_FALSE(test_rvh()->IsFullscreenGranted());
  EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
  EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
  contents()->GetMainFrame()->OnMessageReceived(FrameHostMsg_ToggleFullscreen(
      contents()->GetMainFrame()->GetRoutingID(), true));
  EXPECT_TRUE(test_rvh()->IsFullscreenGranted());
  EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
  EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));

  // Crash the renderer.
  main_test_rfh()->GetProcess()->SimulateCrash();

  // Confirm fullscreen has exited.
  EXPECT_FALSE(test_rvh()->IsFullscreenGranted());
  EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
  EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));

  contents()->SetDelegate(nullptr);
}

////////////////////////////////////////////////////////////////////////////////
// Interstitial Tests
////////////////////////////////////////////////////////////////////////////////

// Test navigating to a page (with the navigation initiated from the browser,
// as when a URL is typed in the location bar) that shows an interstitial and
// creates a new navigation entry, then hiding it without proceeding.
TEST_F(WebContentsImplTest,
       ShowInterstitialFromBrowserWithNewNavigationDontProceed) {
  // Navigate to a page.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Initiate a browser navigation that will trigger the interstitial.
  controller().LoadURL(GURL("http://www.evil.com"), Referrer(),
                       ui::PAGE_TRANSITION_TYPED, std::string());
  NavigationEntry* entry = controller().GetPendingEntry();

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  // The interstitial should not show until its navigation has committed.
  EXPECT_FALSE(interstitial->is_showing());
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  // Let's commit the interstitial navigation.
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
  entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url2);

  // Now don't proceed.
  interstitial->DontProceed();
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page (with the navigation initiated from the renderer,
// as when clicking on a link in the page) that shows an interstitial and
// creates a new navigation entry, then hiding it without proceeding.
TEST_F(WebContentsImplTest,
       ShowInterstitialFromRendererWithNewNavigationDontProceed) {
  // Navigate to a page.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show an interstitial (no pending entry, the interstitial would have been
  // triggered by clicking on a link).
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  // The interstitial should not show until its navigation has committed.
  EXPECT_FALSE(interstitial->is_showing());
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  // Let's commit the interstitial navigation.
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url2);

  // Now don't proceed.
  interstitial->DontProceed();
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page that shows an interstitial without creating a new
// navigation entry (this happens when the interstitial is triggered by a
// sub-resource in the page), then hiding it without proceeding.
TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) {
  // Navigate to a page.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), false, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  // The interstitial should not show until its navigation has committed.
  EXPECT_FALSE(interstitial->is_showing());
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  // Let's commit the interstitial navigation.
  interstitial->TestDidNavigate(1, 0, true, url2);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  // The URL specified to the interstitial should have been ignored.
  EXPECT_TRUE(entry->GetURL() == url1);

  // Now don't proceed.
  interstitial->DontProceed();
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page (with the navigation initiated from the browser,
// as when a URL is typed in the location bar) that shows an interstitial and
// creates a new navigation entry, then proceeding.
TEST_F(WebContentsImplTest,
       ShowInterstitialFromBrowserNewNavigationProceed) {
  // Navigate to a page.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Initiate a browser navigation that will trigger the interstitial
  controller().LoadURL(GURL("http://www.evil.com"), Referrer(),
                        ui::PAGE_TRANSITION_TYPED, std::string());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  // The interstitial should not show until its navigation has committed.
  EXPECT_FALSE(interstitial->is_showing());
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  // Let's commit the interstitial navigation.
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url2);

  // Then proceed.
  interstitial->Proceed();
  // The interstitial should show until the new navigation commits.
  RunAllPendingInMessageLoop();
  ASSERT_FALSE(deleted);
  EXPECT_EQ(TestInterstitialPage::OKED, state);
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);

  // Simulate the navigation to the page, that's when the interstitial gets
  // hidden.
  GURL url3("http://www.thepage.com");
  contents()->GetMainFrame()->PrepareForCommit();
  contents()->GetMainFrame()->SendNavigate(2, 0, true, url3);

  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url3);

  EXPECT_EQ(2, controller().GetEntryCount());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page (with the navigation initiated from the renderer,
// as when clicking on a link in the page) that shows an interstitial and
// creates a new navigation entry, then proceeding.
TEST_F(WebContentsImplTest,
       ShowInterstitialFromRendererNewNavigationProceed) {
  // Navigate to a page.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  // The interstitial should not show until its navigation has committed.
  EXPECT_FALSE(interstitial->is_showing());
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  // Let's commit the interstitial navigation.
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url2);

  // Then proceed.
  interstitial->Proceed();
  // The interstitial should show until the new navigation commits.
  RunAllPendingInMessageLoop();
  ASSERT_FALSE(deleted);
  EXPECT_EQ(TestInterstitialPage::OKED, state);
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);

  // Simulate the navigation to the page, that's when the interstitial gets
  // hidden.
  GURL url3("http://www.thepage.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(2, true, url3);

  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url3);

  EXPECT_EQ(2, controller().GetEntryCount());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page that shows an interstitial without creating a new
// navigation entry (this happens when the interstitial is triggered by a
// sub-resource in the page), then proceeding.
TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationProceed) {
  // Navigate to a page so we have a navigation entry in the controller.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), false, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  // The interstitial should not show until its navigation has committed.
  EXPECT_FALSE(interstitial->is_showing());
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  // Let's commit the interstitial navigation.
  interstitial->TestDidNavigate(1, 0, true, url2);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_TRUE(contents()->ShowingInterstitialPage());
  EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  // The URL specified to the interstitial should have been ignored.
  EXPECT_TRUE(entry->GetURL() == url1);

  // Then proceed.
  interstitial->Proceed();
  // Since this is not a new navigation, the previous page is dismissed right
  // away and shows the original page.
  EXPECT_EQ(TestInterstitialPage::OKED, state);
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == url1);

  EXPECT_EQ(1, controller().GetEntryCount());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page that shows an interstitial, then navigating away.
TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
  // Show interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);

  // While interstitial showing, navigate to a new URL.
  const GURL url2("http://www.yahoo.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url2);

  EXPECT_EQ(TestInterstitialPage::CANCELED, state);

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page that shows an interstitial, then going back.
TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
  // Navigate to a page so we have a navigation entry in the controller.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());
  NavigationEntry* entry = controller().GetLastCommittedEntry();

  // Show interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL interstitial_url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, interstitial_url,
                               &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(2, interstitial_entry_id, true,
                                interstitial_url);

  // While the interstitial is showing, go back.
  controller().GoBack();
  main_test_rfh()->PrepareForCommit();
  contents()->GetMainFrame()->SendNavigate(1, entry->GetUniqueID(), false,
                                           url1);

  // Make sure we are back to the original page and that the interstitial is
  // gone.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  entry = controller().GetVisibleEntry();
  ASSERT_TRUE(entry);
  EXPECT_EQ(url1.spec(), entry->GetURL().spec());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page that shows an interstitial, has a renderer crash,
// and then goes back.
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
  // Navigate to a page so we have a navigation entry in the controller.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());
  NavigationEntry* entry = controller().GetLastCommittedEntry();

  // Show interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL interstitial_url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, interstitial_url,
                               &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(2, interstitial_entry_id, true,
                                interstitial_url);

  // Crash the renderer
  contents()->GetMainFrame()->GetProcess()->SimulateCrash();

  // While the interstitial is showing, go back. This will dismiss the
  // interstitial and not initiate a navigation, but just show the existing
  // RenderFrameHost.
  controller().GoBack();

  // Make sure we are back to the original page and that the interstitial is
  // gone.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  entry = controller().GetVisibleEntry();
  ASSERT_TRUE(entry);
  EXPECT_EQ(url1.spec(), entry->GetURL().spec());

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page that shows an interstitial, has the renderer crash,
// and then navigates to the interstitial.
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenNavigate) {
  // Navigate to a page so we have a navigation entry in the controller.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL interstitial_url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, interstitial_url,
                               &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();

  // Crash the renderer
  contents()->GetMainFrame()->GetProcess()->SimulateCrash();

  interstitial->TestDidNavigate(2, interstitial_entry_id, true,
                                interstitial_url);
}

// Test navigating to a page that shows an interstitial, then close the
// contents.
TEST_F(WebContentsImplTest, ShowInterstitialThenCloseTab) {
  // Show interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);

  // Now close the contents.
  DeleteContents();
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test navigating to a page that shows an interstitial, then close the
// contents.
TEST_F(WebContentsImplTest, ShowInterstitialThenCloseAndShutdown) {
  // Show interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);
  TestRenderFrameHost* rfh =
      static_cast<TestRenderFrameHost*>(interstitial->GetMainFrame());

  // Now close the contents.
  DeleteContents();
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);

  // Before the interstitial has a chance to process its shutdown task,
  // simulate quitting the browser.  This goes through all processes and
  // tells them to destruct.
  rfh->GetProcess()->SimulateCrash();

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test that after Proceed is called and an interstitial is still shown, no more
// commands get executed.
TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
  // Navigate to a page so we have a navigation entry in the controller.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);

  // Run a command.
  EXPECT_EQ(0, interstitial->command_received_count());
  interstitial->TestDomOperationResponse("toto");
  EXPECT_EQ(1, interstitial->command_received_count());

  // Then proceed.
  interstitial->Proceed();
  RunAllPendingInMessageLoop();
  ASSERT_FALSE(deleted);

  // While the navigation to the new page is pending, send other commands, they
  // should be ignored.
  interstitial->TestDomOperationResponse("hello");
  interstitial->TestDomOperationResponse("hi");
  EXPECT_EQ(1, interstitial->command_received_count());
}

// Test showing an interstitial while another interstitial is already showing.
TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
  // Navigate to a page so we have a navigation entry in the controller.
  GURL start_url("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, start_url);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state1 =
      TestInterstitialPage::INVALID;
  bool deleted1 = false;
  GURL url1("http://interstitial1");
  TestInterstitialPage* interstitial1 =
      new TestInterstitialPage(contents(), true, url1, &state1, &deleted1);
  TestInterstitialPageStateGuard state_guard1(interstitial1);
  interstitial1->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial1->TestDidNavigate(1, interstitial_entry_id, true, url1);

  // Now show another interstitial.
  TestInterstitialPage::InterstitialState state2 =
      TestInterstitialPage::INVALID;
  bool deleted2 = false;
  GURL url2("http://interstitial2");
  TestInterstitialPage* interstitial2 =
      new TestInterstitialPage(contents(), true, url2, &state2, &deleted2);
  TestInterstitialPageStateGuard state_guard2(interstitial2);
  interstitial2->Show();
  interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial2->TestDidNavigate(1, interstitial_entry_id, true, url2);

  // Showing interstitial2 should have caused interstitial1 to go away.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state1);
  EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2);

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted1);
  ASSERT_FALSE(deleted2);

  // Let's make sure interstitial2 is working as intended.
  interstitial2->Proceed();
  GURL landing_url("http://www.thepage.com");
  contents()->GetMainFrame()->SendNavigate(2, 0, true, landing_url);

  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == landing_url);
  EXPECT_EQ(2, controller().GetEntryCount());
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted2);
}

// Test showing an interstitial, proceeding and then navigating to another
// interstitial.
TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
  // Navigate to a page so we have a navigation entry in the controller.
  GURL start_url("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, start_url);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state1 =
      TestInterstitialPage::INVALID;
  bool deleted1 = false;
  GURL url1("http://interstitial1");
  TestInterstitialPage* interstitial1 =
      new TestInterstitialPage(contents(), true, url1, &state1, &deleted1);
  TestInterstitialPageStateGuard state_guard1(interstitial1);
  interstitial1->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial1->TestDidNavigate(1, interstitial_entry_id, true, url1);

  // Take action.  The interstitial won't be hidden until the navigation is
  // committed.
  interstitial1->Proceed();
  EXPECT_EQ(TestInterstitialPage::OKED, state1);

  // Now show another interstitial (simulating the navigation causing another
  // interstitial).
  TestInterstitialPage::InterstitialState state2 =
      TestInterstitialPage::INVALID;
  bool deleted2 = false;
  GURL url2("http://interstitial2");
  TestInterstitialPage* interstitial2 =
      new TestInterstitialPage(contents(), true, url2, &state2, &deleted2);
  TestInterstitialPageStateGuard state_guard2(interstitial2);
  interstitial2->Show();
  interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial2->TestDidNavigate(1, interstitial_entry_id, true, url2);

  // Showing interstitial2 should have caused interstitial1 to go away.
  EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted1);
  ASSERT_FALSE(deleted2);

  // Let's make sure interstitial2 is working as intended.
  interstitial2->Proceed();
  GURL landing_url("http://www.thepage.com");
  contents()->GetMainFrame()->SendNavigate(2, 0, true, landing_url);

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted2);
  EXPECT_FALSE(contents()->ShowingInterstitialPage());
  EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
  NavigationEntry* entry = controller().GetVisibleEntry();
  ASSERT_NE(nullptr, entry);
  EXPECT_TRUE(entry->GetURL() == landing_url);
  EXPECT_EQ(2, controller().GetEntryCount());
}

// Test that navigating away from an interstitial while it's loading cause it
// not to show.
TEST_F(WebContentsImplTest, NavigateBeforeInterstitialShows) {
  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL interstitial_url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, interstitial_url,
                               &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();

  // Let's simulate a navigation initiated from the browser before the
  // interstitial finishes loading.
  const GURL url("http://www.google.com");
  controller().LoadURL(
      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  EXPECT_FALSE(interstitial->is_showing());
  RunAllPendingInMessageLoop();
  ASSERT_FALSE(deleted);

  // Now let's make the interstitial navigation commit.
  interstitial->TestDidNavigate(1, interstitial_entry_id, true,
                                interstitial_url);

  // After it loaded the interstitial should be gone.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Test that a new request to show an interstitial while an interstitial is
// pending does not cause problems. htp://crbug/29655 and htp://crbug/9442.
TEST_F(WebContentsImplTest, TwoQuickInterstitials) {
  GURL interstitial_url("http://interstitial");

  // Show a first interstitial.
  TestInterstitialPage::InterstitialState state1 =
      TestInterstitialPage::INVALID;
  bool deleted1 = false;
  TestInterstitialPage* interstitial1 =
      new TestInterstitialPage(contents(), true, interstitial_url,
                               &state1, &deleted1);
  TestInterstitialPageStateGuard state_guard1(interstitial1);
  interstitial1->Show();

  // Show another interstitial on that same contents before the first one had
  // time to load.
  TestInterstitialPage::InterstitialState state2 =
      TestInterstitialPage::INVALID;
  bool deleted2 = false;
  TestInterstitialPage* interstitial2 =
      new TestInterstitialPage(contents(), true, interstitial_url,
                               &state2, &deleted2);
  TestInterstitialPageStateGuard state_guard2(interstitial2);
  interstitial2->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();

  // The first interstitial should have been closed and deleted.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state1);
  // The 2nd one should still be OK.
  EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2);

  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted1);
  ASSERT_FALSE(deleted2);

  // Make the interstitial navigation commit it should be showing.
  interstitial2->TestDidNavigate(1, interstitial_entry_id, true,
                                 interstitial_url);
  EXPECT_EQ(interstitial2, contents()->GetInterstitialPage());
}

// Test showing an interstitial and have its renderer crash.
TEST_F(WebContentsImplTest, InterstitialCrasher) {
  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  // Simulate a renderer crash before the interstitial is shown.
  interstitial->TestRenderViewTerminated(
      base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
  // The interstitial should have been dismissed.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);

  // Now try again but this time crash the intersitial after it was shown.
  interstitial =
      new TestInterstitialPage(contents(), true, url, &state, &deleted);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);
  // Simulate a renderer crash.
  interstitial->TestRenderViewTerminated(
      base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
  // The interstitial should have been dismissed.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
}

// Tests that showing an interstitial as a result of a browser initiated
// navigation while an interstitial is showing does not remove the pending
// entry (see http://crbug.com/9791).
TEST_F(WebContentsImplTest, NewInterstitialDoesNotCancelPendingEntry) {
  const char kUrl[] = "http://www.badguys.com/";
  const GURL kGURL(kUrl);

  // Start a navigation to a page
  contents()->GetController().LoadURL(
      kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());

  // Simulate that navigation triggering an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, kGURL, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, kGURL);

  // Initiate a new navigation from the browser that also triggers an
  // interstitial.
  contents()->GetController().LoadURL(
      kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  TestInterstitialPage::InterstitialState state2 =
      TestInterstitialPage::INVALID;
  bool deleted2 = false;
  TestInterstitialPage* interstitial2 =
      new TestInterstitialPage(contents(), true, kGURL, &state2, &deleted2);
  TestInterstitialPageStateGuard state_guard2(interstitial2);
  interstitial2->Show();
  interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial2->TestDidNavigate(1, interstitial_entry_id, true, kGURL);

  // Make sure we still have an entry.
  NavigationEntry* entry = contents()->GetController().GetPendingEntry();
  ASSERT_TRUE(entry);
  EXPECT_EQ(kUrl, entry->GetURL().spec());

  // And that the first interstitial is gone, but not the second.
  EXPECT_EQ(TestInterstitialPage::CANCELED, state);
  EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(deleted);
  EXPECT_FALSE(deleted2);
}

// Tests that Javascript messages are not shown while an interstitial is
// showing.
TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
  const char kUrl[] = "http://www.badguys.com/";
  const GURL kGURL(kUrl);

  // Start a navigation to a page
  contents()->GetController().LoadURL(
      kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  main_test_rfh()->PrepareForCommit();
  // DidNavigate from the page
  contents()->TestDidNavigate(contents()->GetMainFrame(), 1, entry_id, true,
                              kGURL, ui::PAGE_TRANSITION_TYPED);

  // Simulate showing an interstitial while the page is showing.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, kGURL, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, kGURL);

  // While the interstitial is showing, let's simulate the hidden page
  // attempting to show a JS message.
  IPC::Message* dummy_message = new IPC::Message;
  contents()->RunJavaScriptMessage(contents()->GetMainFrame(),
      base::ASCIIToUTF16("This is an informative message"),
      base::ASCIIToUTF16("OK"),
      kGURL, JAVASCRIPT_MESSAGE_TYPE_ALERT, dummy_message);
  EXPECT_TRUE(contents()->last_dialog_suppressed_);
}

// Makes sure that if the source passed to CopyStateFromAndPrune has an
// interstitial it isn't copied over to the destination.
TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
  // Navigate to a page.
  GURL url1("http://www.google.com");
  main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
  EXPECT_EQ(1, controller().GetEntryCount());

  // Initiate a browser navigation that will trigger the interstitial
  controller().LoadURL(GURL("http://www.evil.com"), Referrer(),
                        ui::PAGE_TRANSITION_TYPED, std::string());

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url2("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(contents(), true, url2, &state, &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_EQ(2, controller().GetEntryCount());

  // Create another NavigationController.
  GURL url3("http://foo2");
  scoped_ptr<TestWebContents> other_contents(
      static_cast<TestWebContents*>(CreateTestWebContents()));
  NavigationControllerImpl& other_controller = other_contents->GetController();
  other_contents->NavigateAndCommit(url3);
  other_contents->ExpectSetHistoryOffsetAndLength(1, 2);
  other_controller.CopyStateFromAndPrune(&controller(), false);

  // The merged controller should only have two entries: url1 and url2.
  ASSERT_EQ(2, other_controller.GetEntryCount());
  EXPECT_EQ(1, other_controller.GetCurrentEntryIndex());
  EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
  EXPECT_EQ(url3, other_controller.GetEntryAtIndex(1)->GetURL());

  // And the merged controller shouldn't be showing an interstitial.
  EXPECT_FALSE(other_contents->ShowingInterstitialPage());
}

// Makes sure that CopyStateFromAndPrune cannot be called if the target is
// showing an interstitial.
TEST_F(WebContentsImplTest, CopyStateFromAndPruneTargetInterstitial) {
  // Navigate to a page.
  GURL url1("http://www.google.com");
  contents()->NavigateAndCommit(url1);

  // Create another NavigationController.
  scoped_ptr<TestWebContents> other_contents(
      static_cast<TestWebContents*>(CreateTestWebContents()));
  NavigationControllerImpl& other_controller = other_contents->GetController();

  // Navigate it to url2.
  GURL url2("http://foo2");
  other_contents->NavigateAndCommit(url2);

  // Show an interstitial.
  TestInterstitialPage::InterstitialState state =
      TestInterstitialPage::INVALID;
  bool deleted = false;
  GURL url3("http://interstitial");
  TestInterstitialPage* interstitial =
      new TestInterstitialPage(other_contents.get(), true, url3, &state,
                               &deleted);
  TestInterstitialPageStateGuard state_guard(interstitial);
  interstitial->Show();
  int interstitial_entry_id =
      other_controller.GetTransientEntry()->GetUniqueID();
  interstitial->TestDidNavigate(1, interstitial_entry_id, true, url3);
  EXPECT_TRUE(interstitial->is_showing());
  EXPECT_EQ(2, other_controller.GetEntryCount());

  // Ensure that we do not allow calling CopyStateFromAndPrune when an
  // interstitial is showing in the target.
  EXPECT_FALSE(other_controller.CanPruneAllButLastCommitted());
}

// Regression test for http://crbug.com/168611 - the URLs passed by the
// DidFinishLoad and DidFailLoadWithError IPCs should get filtered.
TEST_F(WebContentsImplTest, FilterURLs) {
  TestWebContentsObserver observer(contents());

  // A navigation to about:whatever should always look like a navigation to
  // about:blank
  GURL url_normalized(url::kAboutBlankURL);
  GURL url_from_ipc("about:whatever");

  // We navigate the test WebContents to about:blank, since NavigateAndCommit
  // will use the given URL to create the NavigationEntry as well, and that
  // entry should contain the filtered URL.
  contents()->NavigateAndCommit(url_normalized);

  // Check that an IPC with about:whatever is correctly normalized.
  contents()->TestDidFinishLoad(url_from_ipc);

  EXPECT_EQ(url_normalized, observer.last_url());

  // Create and navigate another WebContents.
  scoped_ptr<TestWebContents> other_contents(
      static_cast<TestWebContents*>(CreateTestWebContents()));
  TestWebContentsObserver other_observer(other_contents.get());
  other_contents->NavigateAndCommit(url_normalized);

  // Check that an IPC with about:whatever is correctly normalized.
  other_contents->TestDidFailLoadWithError(
      url_from_ipc, 1, base::string16());
  EXPECT_EQ(url_normalized, other_observer.last_url());
}

// Test that if a pending contents is deleted before it is shown, we don't
// crash.
TEST_F(WebContentsImplTest, PendingContents) {
  scoped_ptr<TestWebContents> other_contents(
      static_cast<TestWebContents*>(CreateTestWebContents()));
  contents()->AddPendingContents(other_contents.get());
  int route_id = other_contents->GetRenderViewHost()->GetRoutingID();
  other_contents.reset();
  EXPECT_EQ(nullptr, contents()->GetCreatedWindow(route_id));
}

TEST_F(WebContentsImplTest, CapturerOverridesPreferredSize) {
  const gfx::Size original_preferred_size(1024, 768);
  contents()->UpdatePreferredSize(original_preferred_size);

  // With no capturers, expect the preferred size to be the one propagated into
  // WebContentsImpl via the RenderViewHostDelegate interface.
  EXPECT_EQ(contents()->GetCapturerCount(), 0);
  EXPECT_EQ(original_preferred_size, contents()->GetPreferredSize());

  // Increment capturer count, but without specifying a capture size.  Expect
  // a "not set" preferred size.
  contents()->IncrementCapturerCount(gfx::Size());
  EXPECT_EQ(1, contents()->GetCapturerCount());
  EXPECT_EQ(gfx::Size(), contents()->GetPreferredSize());

  // Increment capturer count again, but with an overriding capture size.
  // Expect preferred size to now be overridden to the capture size.
  const gfx::Size capture_size(1280, 720);
  contents()->IncrementCapturerCount(capture_size);
  EXPECT_EQ(2, contents()->GetCapturerCount());
  EXPECT_EQ(capture_size, contents()->GetPreferredSize());

  // Increment capturer count a third time, but the expect that the preferred
  // size is still the first capture size.
  const gfx::Size another_capture_size(720, 480);
  contents()->IncrementCapturerCount(another_capture_size);
  EXPECT_EQ(3, contents()->GetCapturerCount());
  EXPECT_EQ(capture_size, contents()->GetPreferredSize());

  // Decrement capturer count twice, but expect the preferred size to still be
  // overridden.
  contents()->DecrementCapturerCount();
  contents()->DecrementCapturerCount();
  EXPECT_EQ(1, contents()->GetCapturerCount());
  EXPECT_EQ(capture_size, contents()->GetPreferredSize());

  // Decrement capturer count, and since the count has dropped to zero, the
  // original preferred size should be restored.
  contents()->DecrementCapturerCount();
  EXPECT_EQ(0, contents()->GetCapturerCount());
  EXPECT_EQ(original_preferred_size, contents()->GetPreferredSize());
}

TEST_F(WebContentsImplTest, CapturerPreventsHiding) {
  const gfx::Size original_preferred_size(1024, 768);
  contents()->UpdatePreferredSize(original_preferred_size);

  TestRenderWidgetHostView* view = static_cast<TestRenderWidgetHostView*>(
      contents()->GetMainFrame()->GetRenderViewHost()->GetView());

  // With no capturers, setting and un-setting occlusion should change the
  // view's occlusion state.
  EXPECT_FALSE(view->is_showing());
  contents()->WasShown();
  EXPECT_TRUE(view->is_showing());
  contents()->WasHidden();
  EXPECT_FALSE(view->is_showing());
  contents()->WasShown();
  EXPECT_TRUE(view->is_showing());

  // Add a capturer and try to hide the contents. The view will remain visible.
  contents()->IncrementCapturerCount(gfx::Size());
  contents()->WasHidden();
  EXPECT_TRUE(view->is_showing());

  // Remove the capturer, and the WasHidden should take effect.
  contents()->DecrementCapturerCount();
  EXPECT_FALSE(view->is_showing());
}

TEST_F(WebContentsImplTest, CapturerPreventsOcclusion) {
  const gfx::Size original_preferred_size(1024, 768);
  contents()->UpdatePreferredSize(original_preferred_size);

  TestRenderWidgetHostView* view = static_cast<TestRenderWidgetHostView*>(
      contents()->GetMainFrame()->GetRenderViewHost()->GetView());

  // With no capturers, setting and un-setting occlusion should change the
  // view's occlusion state.
  EXPECT_FALSE(view->is_occluded());
  contents()->WasOccluded();
  EXPECT_TRUE(view->is_occluded());
  contents()->WasUnOccluded();
  EXPECT_FALSE(view->is_occluded());
  contents()->WasOccluded();
  EXPECT_TRUE(view->is_occluded());

  // Add a capturer. This should cause the view to be un-occluded.
  contents()->IncrementCapturerCount(gfx::Size());
  EXPECT_FALSE(view->is_occluded());

  // Try to occlude the view. This will fail to propagate because of the
  // active capturer.
  contents()->WasOccluded();
  EXPECT_FALSE(view->is_occluded());

  // Remove the capturer and try again.
  contents()->DecrementCapturerCount();
  EXPECT_FALSE(view->is_occluded());
  contents()->WasOccluded();
  EXPECT_TRUE(view->is_occluded());
}

// Tests that GetLastActiveTime starts with a real, non-zero time and updates
// on activity.
TEST_F(WebContentsImplTest, GetLastActiveTime) {
  // The WebContents starts with a valid creation time.
  EXPECT_FALSE(contents()->GetLastActiveTime().is_null());

  // Reset the last active time to a known-bad value.
  contents()->last_active_time_ = base::TimeTicks();
  ASSERT_TRUE(contents()->GetLastActiveTime().is_null());

  // Simulate activating the WebContents. The active time should update.
  contents()->WasShown();
  EXPECT_FALSE(contents()->GetLastActiveTime().is_null());
}

class ContentsZoomChangedDelegate : public WebContentsDelegate {
 public:
  ContentsZoomChangedDelegate() :
    contents_zoom_changed_call_count_(0),
    last_zoom_in_(false) {
  }

  int GetAndResetContentsZoomChangedCallCount() {
    int count = contents_zoom_changed_call_count_;
    contents_zoom_changed_call_count_ = 0;
    return count;
  }

  bool last_zoom_in() const {
    return last_zoom_in_;
  }

  // WebContentsDelegate:
  void ContentsZoomChange(bool zoom_in) override {
    contents_zoom_changed_call_count_++;
    last_zoom_in_ = zoom_in;
  }

 private:
  int contents_zoom_changed_call_count_;
  bool last_zoom_in_;

  DISALLOW_COPY_AND_ASSIGN(ContentsZoomChangedDelegate);
};

// Tests that some mouseehweel events get turned into browser zoom requests.
TEST_F(WebContentsImplTest, HandleWheelEvent) {
  using blink::WebInputEvent;

  scoped_ptr<ContentsZoomChangedDelegate> delegate(
      new ContentsZoomChangedDelegate());
  contents()->SetDelegate(delegate.get());

  int modifiers = 0;
  // Verify that normal mouse wheel events do nothing to change the zoom level.
  blink::WebMouseWheelEvent event =
      SyntheticWebMouseWheelEventBuilder::Build(0, 1, modifiers, false);
  EXPECT_FALSE(contents()->HandleWheelEvent(event));
  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());

  modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey |
      WebInputEvent::ControlKey;
  event = SyntheticWebMouseWheelEventBuilder::Build(0, 1, modifiers, false);
  EXPECT_FALSE(contents()->HandleWheelEvent(event));
  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());

  // But whenever the ctrl modifier is applied with canScroll=false, they can
  // increase/decrease zoom. Except on MacOS where we never want to adjust zoom
  // with mousewheel.
  modifiers = WebInputEvent::ControlKey;
  event = SyntheticWebMouseWheelEventBuilder::Build(0, 1, modifiers, false);
  event.canScroll = false;
  bool handled = contents()->HandleWheelEvent(event);
#if defined(OS_MACOSX)
  EXPECT_FALSE(handled);
  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
#else
  EXPECT_TRUE(handled);
  EXPECT_EQ(1, delegate->GetAndResetContentsZoomChangedCallCount());
  EXPECT_TRUE(delegate->last_zoom_in());
#endif

  modifiers = WebInputEvent::ControlKey | WebInputEvent::ShiftKey |
      WebInputEvent::AltKey;
  event = SyntheticWebMouseWheelEventBuilder::Build(2, -5, modifiers, false);
  event.canScroll = false;
  handled = contents()->HandleWheelEvent(event);
#if defined(OS_MACOSX)
  EXPECT_FALSE(handled);
  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
#else
  EXPECT_TRUE(handled);
  EXPECT_EQ(1, delegate->GetAndResetContentsZoomChangedCallCount());
  EXPECT_FALSE(delegate->last_zoom_in());
#endif

  // Unless there is no vertical movement.
  event = SyntheticWebMouseWheelEventBuilder::Build(2, 0, modifiers, false);
  EXPECT_FALSE(contents()->HandleWheelEvent(event));
  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());

  // Events containing precise scrolling deltas also shouldn't result in the
  // zoom being adjusted, to avoid accidental adjustments caused by
  // two-finger-scrolling on a touchpad.
  modifiers = WebInputEvent::ControlKey;
  event = SyntheticWebMouseWheelEventBuilder::Build(0, 5, modifiers, true);
  EXPECT_FALSE(contents()->HandleWheelEvent(event));
  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());

  // Ensure pointers to the delegate aren't kept beyond its lifetime.
  contents()->SetDelegate(nullptr);
}

// Tests that GetRelatedActiveContentsCount is shared between related
// SiteInstances and includes WebContents that have not navigated yet.
TEST_F(WebContentsImplTest, ActiveContentsCountBasic) {
  scoped_refptr<SiteInstance> instance1(
      SiteInstance::CreateForURL(browser_context(), GURL("http://a.com")));
  scoped_refptr<SiteInstance> instance2(
      instance1->GetRelatedSiteInstance(GURL("http://b.com")));

  EXPECT_EQ(0u, instance1->GetRelatedActiveContentsCount());
  EXPECT_EQ(0u, instance2->GetRelatedActiveContentsCount());

  scoped_ptr<TestWebContents> contents1(
      TestWebContents::Create(browser_context(), instance1.get()));
  EXPECT_EQ(1u, instance1->GetRelatedActiveContentsCount());
  EXPECT_EQ(1u, instance2->GetRelatedActiveContentsCount());

  scoped_ptr<TestWebContents> contents2(
      TestWebContents::Create(browser_context(), instance1.get()));
  EXPECT_EQ(2u, instance1->GetRelatedActiveContentsCount());
  EXPECT_EQ(2u, instance2->GetRelatedActiveContentsCount());

  contents1.reset();
  EXPECT_EQ(1u, instance1->GetRelatedActiveContentsCount());
  EXPECT_EQ(1u, instance2->GetRelatedActiveContentsCount());

  contents2.reset();
  EXPECT_EQ(0u, instance1->GetRelatedActiveContentsCount());
  EXPECT_EQ(0u, instance2->GetRelatedActiveContentsCount());
}

// Tests that GetRelatedActiveContentsCount is preserved correctly across
// same-site and cross-site navigations.
TEST_F(WebContentsImplTest, ActiveContentsCountNavigate) {
  scoped_refptr<SiteInstance> instance(
      SiteInstance::Create(browser_context()));

  EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());

  scoped_ptr<TestWebContents> contents(
      TestWebContents::Create(browser_context(), instance.get()));
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());

  // Navigate to a URL.
  contents->GetController().LoadURL(GURL("http://a.com/1"),
                                    Referrer(),
                                    ui::PAGE_TRANSITION_TYPED,
                                    std::string());
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
  contents->CommitPendingNavigation();
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());

  // Navigate to a URL in the same site.
  contents->GetController().LoadURL(GURL("http://a.com/2"),
                                    Referrer(),
                                    ui::PAGE_TRANSITION_TYPED,
                                    std::string());
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
  contents->CommitPendingNavigation();
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());

  // Navigate to a URL in a different site.
  const GURL kUrl = GURL("http://b.com");
  contents->GetController().LoadURL(kUrl,
                                    Referrer(),
                                    ui::PAGE_TRANSITION_TYPED,
                                    std::string());
  int entry_id = contents->GetController().GetPendingEntry()->GetUniqueID();
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableBrowserSideNavigation)) {
    contents->GetMainFrame()->PrepareForCommit();
  }
  EXPECT_TRUE(contents->CrossProcessNavigationPending());
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
  contents->GetPendingMainFrame()->SendNavigate(1, entry_id, true, kUrl);
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());

  contents.reset();
  EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());
}

// Tests that GetRelatedActiveContentsCount tracks BrowsingInstance changes
// from WebUI.
TEST_F(WebContentsImplTest, ActiveContentsCountChangeBrowsingInstance) {
  scoped_refptr<SiteInstance> instance(
      SiteInstance::Create(browser_context()));

  EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());

  scoped_ptr<TestWebContents> contents(
      TestWebContents::Create(browser_context(), instance.get()));
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());

  // Navigate to a URL.
  contents->NavigateAndCommit(GURL("http://a.com"));
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());

  // Navigate to a URL which sort of looks like a chrome:// url.
  contents->NavigateAndCommit(GURL("http://gpu"));
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());

  // Navigate to a URL with WebUI. This will change BrowsingInstances.
  const GURL kWebUIUrl = GURL("chrome://gpu");
  contents->GetController().LoadURL(kWebUIUrl,
                                    Referrer(),
                                    ui::PAGE_TRANSITION_TYPED,
                                    std::string());
  int entry_id = contents->GetController().GetPendingEntry()->GetUniqueID();
  contents->GetMainFrame()->PrepareForCommit();
  EXPECT_TRUE(contents->CrossProcessNavigationPending());
  scoped_refptr<SiteInstance> instance_webui(
      contents->GetPendingMainFrame()->GetSiteInstance());
  EXPECT_FALSE(instance->IsRelatedSiteInstance(instance_webui.get()));

  // At this point, contents still counts for the old BrowsingInstance.
  EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
  EXPECT_EQ(0u, instance_webui->GetRelatedActiveContentsCount());

  // Commit and contents counts for the new one.
  contents->GetPendingMainFrame()->SendNavigate(1, entry_id, true, kWebUIUrl);
  EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());
  EXPECT_EQ(1u, instance_webui->GetRelatedActiveContentsCount());

  contents.reset();
  EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());
  EXPECT_EQ(0u, instance_webui->GetRelatedActiveContentsCount());
}

class LoadingWebContentsObserver : public WebContentsObserver {
 public:
  explicit LoadingWebContentsObserver(WebContents* contents)
      : WebContentsObserver(contents),
        is_loading_(false) {
  }
  ~LoadingWebContentsObserver() override {}

  void DidStartLoading() override { is_loading_ = true; }
  void DidStopLoading() override { is_loading_ = false; }

  bool is_loading() const { return is_loading_; }

 private:
  bool is_loading_;

  DISALLOW_COPY_AND_ASSIGN(LoadingWebContentsObserver);
};

// Ensure that DidStartLoading/DidStopLoading events balance out properly with
// interleaving cross-process navigations in multiple subframes.
// See https://crbug.com/448601 for details of the underlying issue. The
// sequence of events that reproduce it are as follows:
// * Navigate top-level frame with one subframe.
// * Subframe navigates more than once before the top-level frame has had a
//   chance to complete the load.
// The subframe navigations cause the loading_frames_in_progress_ to drop down
// to 0, while the loading_progresses_ map is not reset.
TEST_F(WebContentsImplTest, StartStopEventsBalance) {
  // The bug manifests itself in regular mode as well, but browser-initiated
  // navigation of subframes is only possible in --site-per-process mode within
  // unit tests.
  base::CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kSitePerProcess);
  const GURL initial_url("about:blank");
  const GURL main_url("http://www.chromium.org");
  const GURL foo_url("http://foo.chromium.org");
  const GURL bar_url("http://bar.chromium.org");
  TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();

  // Use a WebContentsObserver to approximate the behavior of the tab's spinner.
  LoadingWebContentsObserver observer(contents());

  // Navigate the main RenderFrame, simulate the DidStartLoading, and commit.
  // The frame should still be loading.
  controller().LoadURL(
      main_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  orig_rfh->PrepareForCommit();
  orig_rfh->OnMessageReceived(
      FrameHostMsg_DidStartLoading(orig_rfh->GetRoutingID(), false));
  contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, main_url,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
  EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
  EXPECT_TRUE(contents()->IsLoading());
  EXPECT_TRUE(observer.is_loading());

  // Create a child frame to navigate multiple times.
  TestRenderFrameHost* subframe = orig_rfh->AppendChild("subframe");

  // Navigate the child frame to about:blank, which will send both
  // DidStartLoading and DidStopLoading messages.
  {
    subframe->SendRendererInitiatedNavigationRequest(initial_url, false);
    subframe->PrepareForCommit();
    subframe->OnMessageReceived(
        FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true));
    subframe->SendNavigateWithTransition(1, 0, false, initial_url,
                                         ui::PAGE_TRANSITION_AUTO_SUBFRAME);
    subframe->OnMessageReceived(
        FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
  }

  // Navigate the frame to another URL, which will send again
  // DidStartLoading and DidStopLoading messages.
  {
    subframe->SendRendererInitiatedNavigationRequest(foo_url, false);
    subframe->PrepareForCommit();
    subframe->OnMessageReceived(
        FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true));
    subframe->SendNavigateWithTransition(1, 0, false, foo_url,
                                         ui::PAGE_TRANSITION_AUTO_SUBFRAME);
    subframe->OnMessageReceived(
        FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
  }

  // Since the main frame hasn't sent any DidStopLoading messages, it is
  // expected that the WebContents is still in loading state.
  EXPECT_TRUE(contents()->IsLoading());
  EXPECT_TRUE(observer.is_loading());

  // Navigate the frame again, this time using LoadURLWithParams. This causes
  // RenderFrameHost to call into WebContents::DidStartLoading, which starts
  // the spinner.
  {
    NavigationController::LoadURLParams load_params(bar_url);
    load_params.referrer =
        Referrer(GURL("http://referrer"), blink::WebReferrerPolicyDefault);
    load_params.transition_type = ui::PAGE_TRANSITION_GENERATED;
    load_params.extra_headers = "content-type: text/plain";
    load_params.load_type = NavigationController::LOAD_TYPE_DEFAULT;
    load_params.is_renderer_initiated = false;
    load_params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
    load_params.frame_tree_node_id =
        subframe->frame_tree_node()->frame_tree_node_id();
    controller().LoadURLWithParams(load_params);
    entry_id = controller().GetPendingEntry()->GetUniqueID();

    subframe->OnMessageReceived(
        FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true));

    // Commit the navigation in the child frame and send the DidStopLoading
    // message.
    subframe->PrepareForCommit();
    contents()->TestDidNavigate(subframe, 3, entry_id, true, bar_url,
                                ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
    subframe->OnMessageReceived(
        FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
  }

  // At this point the status should still be loading, since the main frame
  // hasn't sent the DidstopLoading message yet.
  EXPECT_TRUE(contents()->IsLoading());
  EXPECT_TRUE(observer.is_loading());

  // Send the DidStopLoading for the main frame and ensure it isn't loading
  // anymore.
  orig_rfh->OnMessageReceived(
      FrameHostMsg_DidStopLoading(orig_rfh->GetRoutingID()));
  EXPECT_FALSE(contents()->IsLoading());
  EXPECT_FALSE(observer.is_loading());
}

// Ensure that WebContentsImpl does not stop loading too early when there still
// is a pending renderer. This can happen if a same-process non user-initiated
// navigation completes while there is an ongoing cross-process navigation.
// TODO(fdegans): Rewrite the test for PlzNavigate when DidStartLoading and
// DidStopLoading are properly called.
TEST_F(WebContentsImplTest, NoEarlyStop) {
  const GURL kUrl1("http://www.chromium.org");
  const GURL kUrl2("http://www.google.com");
  const GURL kUrl3("http://www.wikipedia.org");

  contents()->NavigateAndCommit(kUrl1);

  TestRenderFrameHost* current_rfh = contents()->GetMainFrame();

  // Start a browser-initiated cross-process navigation to |kUrl2|. There should
  // be a pending RenderFrameHost and the WebContents should be loading.
  controller().LoadURL(
      kUrl2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
  TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
  ASSERT_TRUE(pending_rfh);
  EXPECT_TRUE(contents()->IsLoading());

  // The current RenderFrameHost starts a non user-initiated render-initiated
  // navigation and sends a DidStartLoading IPC. The WebContents should still be
  // loading.
  current_rfh->OnMessageReceived(
      FrameHostMsg_DidStartLoading(current_rfh->GetRoutingID(), false));
  EXPECT_TRUE(contents()->IsLoading());

  // Simulate the pending RenderFrameHost DidStartLoading. There should still be
  // a pending RenderFrameHost and the WebContents should still be loading.
  pending_rfh->PrepareForCommit();
  pending_rfh->OnMessageReceived(
      FrameHostMsg_DidStartLoading(pending_rfh->GetRoutingID(), false));
  EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh);
  EXPECT_TRUE(contents()->IsLoading());

  // Simulate the commit and DidStopLoading from the renderer-initiated
  // navigation in the current RenderFrameHost. There should still be a pending
  // RenderFrameHost and the WebContents should still be loading.
  current_rfh->SendNavigate(1, 0, true, kUrl3);
  current_rfh->OnMessageReceived(
      FrameHostMsg_DidStopLoading(current_rfh->GetRoutingID()));
  EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh);
  EXPECT_TRUE(contents()->IsLoading());

  // Commit the navigation. The formerly pending RenderFrameHost should now be
  // the current RenderFrameHost and the WebContents should still be loading.
  contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, kUrl2,
                              ui::PAGE_TRANSITION_TYPED);
  EXPECT_FALSE(contents()->GetPendingMainFrame());
  TestRenderFrameHost* new_current_rfh = contents()->GetMainFrame();
  EXPECT_EQ(new_current_rfh, pending_rfh);
  EXPECT_TRUE(contents()->IsLoading());

  // Simulate the new current RenderFrameHost DidStopLoading. The WebContents
  // should now have stopped loading.
  new_current_rfh->OnMessageReceived(
      FrameHostMsg_DidStopLoading(new_current_rfh->GetRoutingID()));
  EXPECT_EQ(contents()->GetMainFrame(), new_current_rfh);
  EXPECT_FALSE(contents()->IsLoading());
}

TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
  // PlayerIDs are actually pointers cast to int64, so verify that both negative
  // and positive player ids don't blow up.
  const int kPlayerAudioVideoId = 15;
  const int kPlayerAudioOnlyId = -15;
  const int kPlayerVideoOnlyId = 30;
  const int kPlayerRemoteId = -30;

  EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
  EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());

  TestRenderFrameHost* rfh = contents()->GetMainFrame();
  AudioStateProvider* audio_state = contents()->audio_state_provider();

  // Ensure RenderFrame is initialized before simulating events coming from it.
  main_test_rfh()->InitializeRenderFrameIfNeeded();

  // The audio power save blocker should not be based on having a media player
  // when audio stream monitoring is available.
  if (audio_state->IsAudioStateAvailable()) {
    // Send a fake audio stream monitor notification.  The audio power save
    // blocker should be created.
    audio_state->set_was_recently_audible_for_testing(true);
    contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
    EXPECT_TRUE(contents()->has_audio_power_save_blocker_for_testing());

    // Send another fake notification, this time when WasRecentlyAudible() will
    // be false.  The power save blocker should be released.
    audio_state->set_was_recently_audible_for_testing(false);
    contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
    EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
  }

  // Start a player with both audio and video.  A video power save blocker
  // should be created.  If audio stream monitoring is available, an audio power
  // save blocker should be created too.
  rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
      0, kPlayerAudioVideoId, true, true, false));
  EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
            !audio_state->IsAudioStateAvailable());

  // Upon hiding the video power save blocker should be released.
  contents()->WasHidden();
  EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());

  // Start another player that only has video.  There should be no change in
  // the power save blockers.  The notification should take into account the
  // visibility state of the WebContents.
  rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
      0, kPlayerVideoOnlyId, true, false, false));
  EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
            !audio_state->IsAudioStateAvailable());

  // Showing the WebContents should result in the creation of the blocker.
  contents()->WasShown();
  EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());

  // Start another player that only has audio.  There should be no change in
  // the power save blockers.
  rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
      0, kPlayerAudioOnlyId, false, true, false));
  EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
            !audio_state->IsAudioStateAvailable());

  // Start a remote player. There should be no change in the power save
  // blockers.
  rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
      0, kPlayerRemoteId, true, true, true));
  EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
            !audio_state->IsAudioStateAvailable());

  // Destroy the original audio video player.  Both power save blockers should
  // remain.
  rfh->OnMessageReceived(
      FrameHostMsg_MediaPausedNotification(0, kPlayerAudioVideoId));
  EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
            !audio_state->IsAudioStateAvailable());

  // Destroy the audio only player.  The video power save blocker should remain.
  rfh->OnMessageReceived(
      FrameHostMsg_MediaPausedNotification(0, kPlayerAudioOnlyId));
  EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());

  // Destroy the video only player.  No power save blockers should remain.
  rfh->OnMessageReceived(
      FrameHostMsg_MediaPausedNotification(0, kPlayerVideoOnlyId));
  EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());

  // Destroy the remote player. No power save blockers should remain.
  rfh->OnMessageReceived(
      FrameHostMsg_MediaPausedNotification(0, kPlayerRemoteId));
  EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());

  // Start a player with both audio and video.  A video power save blocker
  // should be created.  If audio stream monitoring is available, an audio power
  // save blocker should be created too.
  rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
      0, kPlayerAudioVideoId, true, true, false));
  EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
            !audio_state->IsAudioStateAvailable());

  // Crash the renderer.
  contents()->GetMainFrame()->GetProcess()->SimulateCrash();

  // Verify that all the power save blockers have been released.
  EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
  EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
}

TEST_F(WebContentsImplTest, ThemeColorChangeDependingOnFirstVisiblePaint) {
  TestWebContentsObserver observer(contents());
  TestRenderFrameHost* rfh = contents()->GetMainFrame();

  SkColor transparent = SK_ColorTRANSPARENT;

  EXPECT_EQ(transparent, contents()->GetThemeColor());
  EXPECT_EQ(transparent, observer.last_theme_color());

  // Theme color changes should not propagate past the WebContentsImpl before
  // the first visually non-empty paint has occurred.
  RenderViewHostTester::TestOnMessageReceived(
      test_rvh(),
      FrameHostMsg_DidChangeThemeColor(rfh->GetRoutingID(), SK_ColorRED));

  EXPECT_EQ(SK_ColorRED, contents()->GetThemeColor());
  EXPECT_EQ(transparent, observer.last_theme_color());

  // Simulate that the first visually non-empty paint has occurred. This will
  // propagate the current theme color to the delegates.
  RenderViewHostTester::TestOnMessageReceived(
      test_rvh(),
      FrameHostMsg_DidFirstVisuallyNonEmptyPaint(rfh->GetRoutingID()));

  EXPECT_EQ(SK_ColorRED, contents()->GetThemeColor());
  EXPECT_EQ(SK_ColorRED, observer.last_theme_color());

  // Additional changes made by the web contents should propagate as well.
  RenderViewHostTester::TestOnMessageReceived(
      test_rvh(),
      FrameHostMsg_DidChangeThemeColor(rfh->GetRoutingID(), SK_ColorGREEN));

  EXPECT_EQ(SK_ColorGREEN, contents()->GetThemeColor());
  EXPECT_EQ(SK_ColorGREEN, observer.last_theme_color());
}

}  // namespace content
