Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/test/base/browser_with_test_window_test.h"
      6 
      7 #include "base/run_loop.h"
      8 #include "chrome/browser/profiles/profile_destroyer.h"
      9 #include "chrome/browser/ui/browser.h"
     10 #include "chrome/browser/ui/browser_navigator.h"
     11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     12 #include "chrome/common/render_messages.h"
     13 #include "chrome/test/base/testing_profile.h"
     14 #include "content/public/browser/navigation_controller.h"
     15 #include "content/public/browser/navigation_entry.h"
     16 #include "content/public/browser/web_contents.h"
     17 #include "content/public/common/page_transition_types.h"
     18 #include "content/public/test/test_renderer_host.h"
     19 
     20 #if defined(USE_AURA)
     21 #include "ui/aura/test/aura_test_helper.h"
     22 #endif
     23 
     24 #if defined(USE_ASH)
     25 #include "ash/test/ash_test_helper.h"
     26 #endif
     27 
     28 using content::NavigationController;
     29 using content::RenderViewHost;
     30 using content::RenderViewHostTester;
     31 using content::WebContents;
     32 
     33 BrowserWithTestWindowTest::BrowserWithTestWindowTest()
     34     : host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE) {
     35 }
     36 
     37 BrowserWithTestWindowTest::~BrowserWithTestWindowTest() {
     38 }
     39 
     40 void BrowserWithTestWindowTest::SetHostDesktopType(
     41     chrome::HostDesktopType host_desktop_type) {
     42   DCHECK(!window_);
     43   host_desktop_type_ = host_desktop_type;
     44 }
     45 
     46 void BrowserWithTestWindowTest::SetUp() {
     47   testing::Test::SetUp();
     48 #if defined(OS_CHROMEOS)
     49   // TODO(jamescook): Windows Ash support. This will require refactoring
     50   // AshTestHelper and AuraTestHelper so they can be used at the same time,
     51   // perhaps by AshTestHelper owning an AuraTestHelper.
     52   ash_test_helper_.reset(new ash::test::AshTestHelper(
     53       base::MessageLoopForUI::current()));
     54   ash_test_helper_->SetUp(true);
     55 #elif defined(USE_AURA)
     56   aura_test_helper_.reset(new aura::test::AuraTestHelper(
     57       base::MessageLoopForUI::current()));
     58   aura_test_helper_->SetUp();
     59 #endif  // USE_AURA
     60 
     61   // Subclasses can provide their own Profile.
     62   profile_.reset(CreateProfile());
     63   // Subclasses can provide their own test BrowserWindow. If they return NULL
     64   // then Browser will create the a production BrowserWindow and the subclass
     65   // is responsible for cleaning it up (usually by NativeWidget destruction).
     66   window_.reset(CreateBrowserWindow());
     67 
     68   Browser::CreateParams params(profile(), host_desktop_type_);
     69   params.window = window_.get();
     70   browser_.reset(new Browser(params));
     71 }
     72 
     73 void BrowserWithTestWindowTest::TearDown() {
     74   // Some tests end up posting tasks to the DB thread that must be completed
     75   // before the profile can be destroyed and the test safely shut down.
     76   base::RunLoop().RunUntilIdle();
     77 
     78   // Reset the profile here because some profile keyed services (like the
     79   // audio service) depend on test stubs that the helpers below will remove.
     80   DestroyBrowserAndProfile();
     81 
     82 #if defined(OS_CHROMEOS)
     83   ash_test_helper_->TearDown();
     84 #elif defined(USE_AURA)
     85   aura_test_helper_->TearDown();
     86 #endif
     87   testing::Test::TearDown();
     88 
     89   // A Task is leaked if we don't destroy everything, then run the message
     90   // loop.
     91   base::MessageLoop::current()->PostTask(FROM_HERE,
     92                                          base::MessageLoop::QuitClosure());
     93   base::MessageLoop::current()->Run();
     94 }
     95 
     96 void BrowserWithTestWindowTest::AddTab(Browser* browser, const GURL& url) {
     97   chrome::NavigateParams params(browser, url, content::PAGE_TRANSITION_TYPED);
     98   params.tabstrip_index = 0;
     99   params.disposition = NEW_FOREGROUND_TAB;
    100   chrome::Navigate(&params);
    101   CommitPendingLoad(&params.target_contents->GetController());
    102 }
    103 
    104 void BrowserWithTestWindowTest::CommitPendingLoad(
    105   NavigationController* controller) {
    106   if (!controller->GetPendingEntry())
    107     return;  // Nothing to commit.
    108 
    109   RenderViewHost* old_rvh =
    110       controller->GetWebContents()->GetRenderViewHost();
    111 
    112   RenderViewHost* pending_rvh = RenderViewHostTester::GetPendingForController(
    113       controller);
    114   if (pending_rvh) {
    115     // Simulate the ShouldClose_ACK that is received from the current renderer
    116     // for a cross-site navigation.
    117     DCHECK_NE(old_rvh, pending_rvh);
    118     RenderViewHostTester::For(old_rvh)->SendShouldCloseACK(true);
    119   }
    120   // Commit on the pending_rvh, if one exists.
    121   RenderViewHost* test_rvh = pending_rvh ? pending_rvh : old_rvh;
    122   RenderViewHostTester* test_rvh_tester = RenderViewHostTester::For(test_rvh);
    123 
    124   // Simulate a SwapOut_ACK before the navigation commits.
    125   if (pending_rvh)
    126     RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK();
    127 
    128   // For new navigations, we need to send a larger page ID. For renavigations,
    129   // we need to send the preexisting page ID. We can tell these apart because
    130   // renavigations will have a pending_entry_index while new ones won't (they'll
    131   // just have a standalong pending_entry that isn't in the list already).
    132   if (controller->GetPendingEntryIndex() >= 0) {
    133     test_rvh_tester->SendNavigateWithTransition(
    134         controller->GetPendingEntry()->GetPageID(),
    135         controller->GetPendingEntry()->GetURL(),
    136         controller->GetPendingEntry()->GetTransitionType());
    137   } else {
    138     test_rvh_tester->SendNavigateWithTransition(
    139         controller->GetWebContents()->
    140             GetMaxPageIDForSiteInstance(test_rvh->GetSiteInstance()) + 1,
    141         controller->GetPendingEntry()->GetURL(),
    142         controller->GetPendingEntry()->GetTransitionType());
    143   }
    144 }
    145 
    146 void BrowserWithTestWindowTest::NavigateAndCommit(
    147     NavigationController* controller,
    148     const GURL& url) {
    149   controller->LoadURL(
    150       url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
    151   CommitPendingLoad(controller);
    152 }
    153 
    154 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL& url) {
    155   NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
    156                         GetController(),
    157                     url);
    158 }
    159 
    160 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
    161     Browser* navigating_browser,
    162     const GURL& url,
    163     const string16& title) {
    164   NavigationController* controller = &navigating_browser->tab_strip_model()->
    165       GetActiveWebContents()->GetController();
    166   NavigateAndCommit(controller, url);
    167   controller->GetActiveEntry()->SetTitle(title);
    168 }
    169 
    170 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
    171   if (browser_.get()) {
    172     // Make sure we close all tabs, otherwise Browser isn't happy in its
    173     // destructor.
    174     browser()->tab_strip_model()->CloseAllTabs();
    175     browser_.reset(NULL);
    176   }
    177   window_.reset(NULL);
    178   // Destroy the profile here - otherwise, if the profile is freed in the
    179   // destructor, and a test subclass owns a resource that the profile depends
    180   // on (such as g_browser_process()->local_state()) there's no way for the
    181   // subclass to free it after the profile.
    182   profile_.reset(NULL);
    183 }
    184 
    185 TestingProfile* BrowserWithTestWindowTest::CreateProfile() {
    186   return new TestingProfile();
    187 }
    188 
    189 BrowserWindow* BrowserWithTestWindowTest::CreateBrowserWindow() {
    190   return new TestBrowserWindow();
    191 }
    192