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 #include "ui/compositor/compositor.h"
     23 #include "ui/compositor/test/context_factories_for_test.h"
     24 #include "ui/wm/core/default_activation_client.h"
     25 #endif
     26 
     27 #if defined(USE_ASH)
     28 #include "ash/test/ash_test_helper.h"
     29 #include "ash/test/ash_test_views_delegate.h"
     30 #endif
     31 
     32 #if defined(TOOLKIT_VIEWS)
     33 #include "ui/views/test/test_views_delegate.h"
     34 #endif
     35 
     36 using content::NavigationController;
     37 using content::RenderViewHost;
     38 using content::RenderViewHostTester;
     39 using content::WebContents;
     40 
     41 BrowserWithTestWindowTest::BrowserWithTestWindowTest()
     42     : browser_type_(Browser::TYPE_TABBED),
     43       host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE),
     44       hosted_app_(false) {
     45 }
     46 
     47 BrowserWithTestWindowTest::BrowserWithTestWindowTest(
     48     Browser::Type browser_type,
     49     chrome::HostDesktopType host_desktop_type,
     50     bool hosted_app)
     51     : browser_type_(browser_type),
     52       host_desktop_type_(host_desktop_type),
     53       hosted_app_(hosted_app) {
     54 }
     55 
     56 BrowserWithTestWindowTest::~BrowserWithTestWindowTest() {
     57 }
     58 
     59 void BrowserWithTestWindowTest::SetUp() {
     60   testing::Test::SetUp();
     61 #if defined(OS_CHROMEOS)
     62   // TODO(jamescook): Windows Ash support. This will require refactoring
     63   // AshTestHelper and AuraTestHelper so they can be used at the same time,
     64   // perhaps by AshTestHelper owning an AuraTestHelper. Also, need to cleanup
     65   // CreateViewsDelegate() below when cleanup done.
     66   ash_test_helper_.reset(new ash::test::AshTestHelper(
     67       base::MessageLoopForUI::current()));
     68   ash_test_helper_->SetUp(true);
     69 #elif defined(USE_AURA)
     70   // The ContextFactory must exist before any Compositors are created.
     71   bool enable_pixel_output = false;
     72   ui::ContextFactory* context_factory =
     73       ui::InitializeContextFactoryForTests(enable_pixel_output);
     74 
     75   aura_test_helper_.reset(new aura::test::AuraTestHelper(
     76       base::MessageLoopForUI::current()));
     77   aura_test_helper_->SetUp(context_factory);
     78   new wm::DefaultActivationClient(aura_test_helper_->root_window());
     79 #endif  // USE_AURA
     80 #if !defined(OS_CHROMEOS) && defined(TOOLKIT_VIEWS)
     81   views_delegate_.reset(CreateViewsDelegate());
     82 #endif
     83 
     84   // Subclasses can provide their own Profile.
     85   profile_ = CreateProfile();
     86   // Subclasses can provide their own test BrowserWindow. If they return NULL
     87   // then Browser will create the a production BrowserWindow and the subclass
     88   // is responsible for cleaning it up (usually by NativeWidget destruction).
     89   window_.reset(CreateBrowserWindow());
     90 
     91   browser_.reset(CreateBrowser(profile(), browser_type_, hosted_app_,
     92                                host_desktop_type_, window_.get()));
     93 }
     94 
     95 void BrowserWithTestWindowTest::TearDown() {
     96   // Some tests end up posting tasks to the DB thread that must be completed
     97   // before the profile can be destroyed and the test safely shut down.
     98   base::RunLoop().RunUntilIdle();
     99 
    100   // Reset the profile here because some profile keyed services (like the
    101   // audio service) depend on test stubs that the helpers below will remove.
    102   DestroyBrowserAndProfile();
    103 
    104 #if defined(OS_CHROMEOS)
    105   ash_test_helper_->TearDown();
    106 #elif defined(USE_AURA)
    107   aura_test_helper_->TearDown();
    108   ui::TerminateContextFactoryForTests();
    109 #endif
    110   testing::Test::TearDown();
    111 
    112   // A Task is leaked if we don't destroy everything, then run the message
    113   // loop.
    114   base::MessageLoop::current()->PostTask(FROM_HERE,
    115                                          base::MessageLoop::QuitClosure());
    116   base::MessageLoop::current()->Run();
    117 
    118 #if defined(TOOLKIT_VIEWS)
    119   views_delegate_.reset(NULL);
    120 #endif
    121 }
    122 
    123 void BrowserWithTestWindowTest::AddTab(Browser* browser, const GURL& url) {
    124   chrome::NavigateParams params(browser, url, content::PAGE_TRANSITION_TYPED);
    125   params.tabstrip_index = 0;
    126   params.disposition = NEW_FOREGROUND_TAB;
    127   chrome::Navigate(&params);
    128   CommitPendingLoad(&params.target_contents->GetController());
    129 }
    130 
    131 void BrowserWithTestWindowTest::CommitPendingLoad(
    132   NavigationController* controller) {
    133   if (!controller->GetPendingEntry())
    134     return;  // Nothing to commit.
    135 
    136   RenderViewHost* old_rvh =
    137       controller->GetWebContents()->GetRenderViewHost();
    138 
    139   RenderViewHost* pending_rvh = RenderViewHostTester::GetPendingForController(
    140       controller);
    141   if (pending_rvh) {
    142     // Simulate the BeforeUnload_ACK that is received from the current renderer
    143     // for a cross-site navigation.
    144     DCHECK_NE(old_rvh, pending_rvh);
    145     RenderViewHostTester::For(old_rvh)->SendBeforeUnloadACK(true);
    146   }
    147   // Commit on the pending_rvh, if one exists.
    148   RenderViewHost* test_rvh = pending_rvh ? pending_rvh : old_rvh;
    149   RenderViewHostTester* test_rvh_tester = RenderViewHostTester::For(test_rvh);
    150 
    151   // Simulate a SwapOut_ACK before the navigation commits.
    152   if (pending_rvh)
    153     RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK();
    154 
    155   // For new navigations, we need to send a larger page ID. For renavigations,
    156   // we need to send the preexisting page ID. We can tell these apart because
    157   // renavigations will have a pending_entry_index while new ones won't (they'll
    158   // just have a standalong pending_entry that isn't in the list already).
    159   if (controller->GetPendingEntryIndex() >= 0) {
    160     test_rvh_tester->SendNavigateWithTransition(
    161         controller->GetPendingEntry()->GetPageID(),
    162         controller->GetPendingEntry()->GetURL(),
    163         controller->GetPendingEntry()->GetTransitionType());
    164   } else {
    165     test_rvh_tester->SendNavigateWithTransition(
    166         controller->GetWebContents()->
    167             GetMaxPageIDForSiteInstance(test_rvh->GetSiteInstance()) + 1,
    168         controller->GetPendingEntry()->GetURL(),
    169         controller->GetPendingEntry()->GetTransitionType());
    170   }
    171 }
    172 
    173 void BrowserWithTestWindowTest::NavigateAndCommit(
    174     NavigationController* controller,
    175     const GURL& url) {
    176   controller->LoadURL(
    177       url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
    178   CommitPendingLoad(controller);
    179 }
    180 
    181 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL& url) {
    182   NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
    183                         GetController(),
    184                     url);
    185 }
    186 
    187 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
    188     Browser* navigating_browser,
    189     const GURL& url,
    190     const base::string16& title) {
    191   NavigationController* controller = &navigating_browser->tab_strip_model()->
    192       GetActiveWebContents()->GetController();
    193   NavigateAndCommit(controller, url);
    194   controller->GetActiveEntry()->SetTitle(title);
    195 }
    196 
    197 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
    198   if (browser_.get()) {
    199     // Make sure we close all tabs, otherwise Browser isn't happy in its
    200     // destructor.
    201     browser()->tab_strip_model()->CloseAllTabs();
    202     browser_.reset(NULL);
    203   }
    204   window_.reset(NULL);
    205   // Destroy the profile here - otherwise, if the profile is freed in the
    206   // destructor, and a test subclass owns a resource that the profile depends
    207   // on (such as g_browser_process()->local_state()) there's no way for the
    208   // subclass to free it after the profile.
    209   if (profile_)
    210     DestroyProfile(profile_);
    211   profile_ = NULL;
    212 }
    213 
    214 TestingProfile* BrowserWithTestWindowTest::CreateProfile() {
    215   return new TestingProfile();
    216 }
    217 
    218 void BrowserWithTestWindowTest::DestroyProfile(TestingProfile* profile) {
    219   delete profile;
    220 }
    221 
    222 BrowserWindow* BrowserWithTestWindowTest::CreateBrowserWindow() {
    223   return new TestBrowserWindow();
    224 }
    225 
    226 Browser* BrowserWithTestWindowTest::CreateBrowser(
    227     Profile* profile,
    228     Browser::Type browser_type,
    229     bool hosted_app,
    230     chrome::HostDesktopType host_desktop_type,
    231     BrowserWindow* browser_window) {
    232   Browser::CreateParams params(profile, host_desktop_type);
    233   if (hosted_app) {
    234     params = Browser::CreateParams::CreateForApp("Test",
    235                                                  true /* trusted_source */,
    236                                                  gfx::Rect(),
    237                                                  profile,
    238                                                  host_desktop_type);
    239   } else {
    240     params.type = browser_type;
    241   }
    242   params.window = browser_window;
    243   return new Browser(params);
    244 }
    245 
    246 #if !defined(OS_CHROMEOS) && defined(TOOLKIT_VIEWS)
    247 views::ViewsDelegate* BrowserWithTestWindowTest::CreateViewsDelegate() {
    248 #if defined(USE_ASH)
    249   return new ash::test::AshTestViewsDelegate;
    250 #else
    251   return new views::TestViewsDelegate;
    252 #endif
    253 }
    254 #endif
    255