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_ = 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_.reset(CreateBrowser(profile(), host_desktop_type_, window_.get()));
     69 }
     70 
     71 void BrowserWithTestWindowTest::TearDown() {
     72   // Some tests end up posting tasks to the DB thread that must be completed
     73   // before the profile can be destroyed and the test safely shut down.
     74   base::RunLoop().RunUntilIdle();
     75 
     76   // Reset the profile here because some profile keyed services (like the
     77   // audio service) depend on test stubs that the helpers below will remove.
     78   DestroyBrowserAndProfile();
     79 
     80 #if defined(OS_CHROMEOS)
     81   ash_test_helper_->TearDown();
     82 #elif defined(USE_AURA)
     83   aura_test_helper_->TearDown();
     84 #endif
     85   testing::Test::TearDown();
     86 
     87   // A Task is leaked if we don't destroy everything, then run the message
     88   // loop.
     89   base::MessageLoop::current()->PostTask(FROM_HERE,
     90                                          base::MessageLoop::QuitClosure());
     91   base::MessageLoop::current()->Run();
     92 }
     93 
     94 void BrowserWithTestWindowTest::AddTab(Browser* browser, const GURL& url) {
     95   chrome::NavigateParams params(browser, url, content::PAGE_TRANSITION_TYPED);
     96   params.tabstrip_index = 0;
     97   params.disposition = NEW_FOREGROUND_TAB;
     98   chrome::Navigate(&params);
     99   CommitPendingLoad(&params.target_contents->GetController());
    100 }
    101 
    102 void BrowserWithTestWindowTest::CommitPendingLoad(
    103   NavigationController* controller) {
    104   if (!controller->GetPendingEntry())
    105     return;  // Nothing to commit.
    106 
    107   RenderViewHost* old_rvh =
    108       controller->GetWebContents()->GetRenderViewHost();
    109 
    110   RenderViewHost* pending_rvh = RenderViewHostTester::GetPendingForController(
    111       controller);
    112   if (pending_rvh) {
    113     // Simulate the ShouldClose_ACK that is received from the current renderer
    114     // for a cross-site navigation.
    115     DCHECK_NE(old_rvh, pending_rvh);
    116     RenderViewHostTester::For(old_rvh)->SendShouldCloseACK(true);
    117   }
    118   // Commit on the pending_rvh, if one exists.
    119   RenderViewHost* test_rvh = pending_rvh ? pending_rvh : old_rvh;
    120   RenderViewHostTester* test_rvh_tester = RenderViewHostTester::For(test_rvh);
    121 
    122   // Simulate a SwapOut_ACK before the navigation commits.
    123   if (pending_rvh)
    124     RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK();
    125 
    126   // For new navigations, we need to send a larger page ID. For renavigations,
    127   // we need to send the preexisting page ID. We can tell these apart because
    128   // renavigations will have a pending_entry_index while new ones won't (they'll
    129   // just have a standalong pending_entry that isn't in the list already).
    130   if (controller->GetPendingEntryIndex() >= 0) {
    131     test_rvh_tester->SendNavigateWithTransition(
    132         controller->GetPendingEntry()->GetPageID(),
    133         controller->GetPendingEntry()->GetURL(),
    134         controller->GetPendingEntry()->GetTransitionType());
    135   } else {
    136     test_rvh_tester->SendNavigateWithTransition(
    137         controller->GetWebContents()->
    138             GetMaxPageIDForSiteInstance(test_rvh->GetSiteInstance()) + 1,
    139         controller->GetPendingEntry()->GetURL(),
    140         controller->GetPendingEntry()->GetTransitionType());
    141   }
    142 }
    143 
    144 void BrowserWithTestWindowTest::NavigateAndCommit(
    145     NavigationController* controller,
    146     const GURL& url) {
    147   controller->LoadURL(
    148       url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
    149   CommitPendingLoad(controller);
    150 }
    151 
    152 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL& url) {
    153   NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
    154                         GetController(),
    155                     url);
    156 }
    157 
    158 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
    159     Browser* navigating_browser,
    160     const GURL& url,
    161     const string16& title) {
    162   NavigationController* controller = &navigating_browser->tab_strip_model()->
    163       GetActiveWebContents()->GetController();
    164   NavigateAndCommit(controller, url);
    165   controller->GetActiveEntry()->SetTitle(title);
    166 }
    167 
    168 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
    169   if (browser_.get()) {
    170     // Make sure we close all tabs, otherwise Browser isn't happy in its
    171     // destructor.
    172     browser()->tab_strip_model()->CloseAllTabs();
    173     browser_.reset(NULL);
    174   }
    175   window_.reset(NULL);
    176   // Destroy the profile here - otherwise, if the profile is freed in the
    177   // destructor, and a test subclass owns a resource that the profile depends
    178   // on (such as g_browser_process()->local_state()) there's no way for the
    179   // subclass to free it after the profile.
    180   if (profile_)
    181     DestroyProfile(profile_);
    182   profile_ = NULL;
    183 }
    184 
    185 TestingProfile* BrowserWithTestWindowTest::CreateProfile() {
    186   return new TestingProfile();
    187 }
    188 
    189 void BrowserWithTestWindowTest::DestroyProfile(TestingProfile* profile) {
    190   delete profile;
    191 }
    192 
    193 BrowserWindow* BrowserWithTestWindowTest::CreateBrowserWindow() {
    194   return new TestBrowserWindow();
    195 }
    196 
    197 Browser* BrowserWithTestWindowTest::CreateBrowser(
    198     Profile* profile,
    199     chrome::HostDesktopType host_desktop_type,
    200     BrowserWindow* browser_window) {
    201   Browser::CreateParams params(profile, host_desktop_type);
    202   params.window = browser_window;
    203   return new Browser(params);
    204 }
    205