Home | History | Annotate | Download | only in views
      1 // Copyright (c) 2011 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/browser/extensions/browser_action_test_util.h"
      6 #include "chrome/browser/extensions/extension_browsertest.h"
      7 #include "chrome/browser/extensions/extension_service.h"
      8 #include "chrome/browser/profiles/profile.h"
      9 #include "chrome/browser/ui/browser.h"
     10 #include "chrome/browser/ui/views/browser_actions_container.h"
     11 #include "chrome/common/extensions/extension_action.h"
     12 #include "chrome/common/extensions/extension_resource.h"
     13 
     14 class BrowserActionsContainerTest : public ExtensionBrowserTest {
     15  public:
     16   BrowserActionsContainerTest() : browser_(NULL) {
     17   }
     18   virtual ~BrowserActionsContainerTest() {}
     19 
     20   virtual Browser* CreateBrowser(Profile* profile) {
     21     browser_ = InProcessBrowserTest::CreateBrowser(profile);
     22     browser_actions_bar_.reset(new BrowserActionTestUtil(browser_));
     23     return browser_;
     24   }
     25 
     26   Browser* browser() { return browser_; }
     27 
     28   BrowserActionTestUtil* browser_actions_bar() {
     29     return browser_actions_bar_.get();
     30   }
     31 
     32   // Make sure extension with index |extension_index| has an icon.
     33   void EnsureExtensionHasIcon(int extension_index) {
     34     if (!browser_actions_bar_->HasIcon(extension_index)) {
     35       // The icon is loaded asynchronously and a notification is then sent to
     36       // observers. So we wait on it.
     37       browser_actions_bar_->WaitForBrowserActionUpdated(extension_index);
     38     }
     39     EXPECT_TRUE(browser_actions_bar()->HasIcon(extension_index));
     40   }
     41 
     42  private:
     43   scoped_ptr<BrowserActionTestUtil> browser_actions_bar_;
     44 
     45   Browser* browser_;  // Weak.
     46 };
     47 
     48 // Test the basic functionality.
     49 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, Basic) {
     50   BrowserActionsContainer::disable_animations_during_testing_ = true;
     51 
     52   // Load an extension with no browser action.
     53   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     54                                           .AppendASCII("browser_action")
     55                                           .AppendASCII("none")));
     56   // This extension should not be in the model (has no browser action).
     57   EXPECT_EQ(0, browser_actions_bar()->NumberOfBrowserActions());
     58 
     59   // Load an extension with a browser action.
     60   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     61                                           .AppendASCII("browser_action")
     62                                           .AppendASCII("basics")));
     63   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
     64   EnsureExtensionHasIcon(0);
     65 
     66   // Unload the extension.
     67   std::string id = browser_actions_bar()->GetExtensionId(0);
     68   UnloadExtension(id);
     69   EXPECT_EQ(0, browser_actions_bar()->NumberOfBrowserActions());
     70 }
     71 
     72 // TODO(mpcomplete): http://code.google.com/p/chromium/issues/detail?id=38992
     73 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, Visibility) {
     74   BrowserActionsContainer::disable_animations_during_testing_ = true;
     75 
     76   base::TimeTicks start_time = base::TimeTicks::Now();
     77 
     78   // Load extension A (contains browser action).
     79   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     80                                           .AppendASCII("browser_action")
     81                                           .AppendASCII("basics")));
     82   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
     83   EnsureExtensionHasIcon(0);
     84   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
     85   std::string idA = browser_actions_bar()->GetExtensionId(0);
     86 
     87   LOG(INFO) << "Load extension A done  : "
     88             << (base::TimeTicks::Now() - start_time).InMilliseconds()
     89             << " ms" << std::flush;
     90 
     91   // Load extension B (contains browser action).
     92   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     93                                           .AppendASCII("browser_action")
     94                                           .AppendASCII("add_popup")));
     95   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
     96   EnsureExtensionHasIcon(0);
     97   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
     98   std::string idB = browser_actions_bar()->GetExtensionId(1);
     99 
    100   LOG(INFO) << "Load extension B done  : "
    101             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    102             << " ms" << std::flush;
    103 
    104   EXPECT_NE(idA, idB);
    105 
    106   // Load extension C (contains browser action).
    107   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    108                                           .AppendASCII("browser_action")
    109                                           .AppendASCII("remove_popup")));
    110   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    111   EnsureExtensionHasIcon(2);
    112   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    113   std::string idC = browser_actions_bar()->GetExtensionId(2);
    114 
    115   LOG(INFO) << "Load extension C done  : "
    116             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    117             << " ms" << std::flush;
    118 
    119   // Change container to show only one action, rest in overflow: A, [B, C].
    120   browser_actions_bar()->SetIconVisibilityCount(1);
    121   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    122 
    123   LOG(INFO) << "Icon visibility count 1: "
    124             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    125             << " ms" << std::flush;
    126 
    127   // Disable extension A (should disappear). State becomes: B [C].
    128   DisableExtension(idA);
    129   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    130   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    131   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
    132 
    133   LOG(INFO) << "Disable extension A    : "
    134             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    135             << " ms" << std::flush;
    136 
    137   // Enable A again. A should get its spot in the same location and the bar
    138   // should not grow (chevron is showing). For details: http://crbug.com/35349.
    139   // State becomes: A, [B, C].
    140   EnableExtension(idA);
    141   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    142   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    143   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
    144 
    145   LOG(INFO) << "Enable extension A     : "
    146             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    147             << " ms" << std::flush;
    148 
    149   // Disable C (in overflow). State becomes: A, [B].
    150   DisableExtension(idC);
    151   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    152   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    153   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
    154 
    155   LOG(INFO) << "Disable extension C    : "
    156             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    157             << " ms" << std::flush;
    158 
    159   // Enable C again. State becomes: A, [B, C].
    160   EnableExtension(idC);
    161   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    162   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    163   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
    164 
    165   LOG(INFO) << "Enable extension C     : "
    166             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    167             << " ms" << std::flush;
    168 
    169   // Now we have 3 extensions. Make sure they are all visible. State: A, B, C.
    170   browser_actions_bar()->SetIconVisibilityCount(3);
    171   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    172 
    173   LOG(INFO) << "Checkpoint             : "
    174             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    175             << " ms" << std::flush;
    176 
    177   // Disable extension A (should disappear). State becomes: B, C.
    178   DisableExtension(idA);
    179   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    180   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
    181   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
    182 
    183   LOG(INFO) << "Disable extension A    : "
    184             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    185             << " ms" << std::flush;
    186 
    187   // Disable extension B (should disappear). State becomes: C.
    188   DisableExtension(idB);
    189   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
    190   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    191   EXPECT_EQ(idC, browser_actions_bar()->GetExtensionId(0));
    192 
    193   LOG(INFO) << "Disable extension B    : "
    194             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    195             << " ms" << std::flush;
    196 
    197   // Enable B (makes B and C showing now). State becomes: B, C.
    198   EnableExtension(idB);
    199   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    200   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
    201   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
    202 
    203   LOG(INFO) << "Enable extension B     : "
    204             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    205             << " ms" << std::flush;
    206 
    207   // Enable A (makes A, B and C showing now). State becomes: B, C, A.
    208   EnableExtension(idA);
    209   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    210   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    211   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(2));
    212 
    213   LOG(INFO) << "Test complete          : "
    214             << (base::TimeTicks::Now() - start_time).InMilliseconds()
    215             << " ms" << std::flush;
    216 }
    217 
    218 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, ForceHide) {
    219   BrowserActionsContainer::disable_animations_during_testing_ = true;
    220 
    221   // Load extension A (contains browser action).
    222   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    223                                           .AppendASCII("browser_action")
    224                                           .AppendASCII("basics")));
    225   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
    226   EnsureExtensionHasIcon(0);
    227   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    228   std::string idA = browser_actions_bar()->GetExtensionId(0);
    229 
    230   // Force hide this browser action.
    231   ExtensionService* service = browser()->profile()->GetExtensionService();
    232   service->SetBrowserActionVisibility(service->GetExtensionById(idA, false),
    233                                       false);
    234   EXPECT_EQ(0, browser_actions_bar()->VisibleBrowserActions());
    235 
    236   ReloadExtension(idA);
    237 
    238   // The browser action should become visible again.
    239   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    240 }
    241 
    242 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, TestCrash57536) {
    243   LOG(INFO) << "Test starting\n" << std::flush;
    244 
    245   ExtensionService* service = browser()->profile()->GetExtensionService();
    246   const size_t size_before = service->extensions()->size();
    247 
    248   LOG(INFO) << "Loading extension\n" << std::flush;
    249 
    250   // Load extension A (contains browser action).
    251   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    252                                           .AppendASCII("browser_action")
    253                                           .AppendASCII("crash_57536")));
    254 
    255   const Extension* extension = service->extensions()->at(size_before);
    256 
    257   LOG(INFO) << "Creating bitmap\n" << std::flush;
    258 
    259   // Create and cache and empty bitmap.
    260   SkBitmap bitmap;
    261   bitmap.setConfig(SkBitmap::kARGB_8888_Config,
    262                     Extension::kBrowserActionIconMaxSize,
    263                     Extension::kBrowserActionIconMaxSize);
    264   bitmap.allocPixels();
    265 
    266   LOG(INFO) << "Set as cached image\n" << std::flush;
    267 
    268   gfx::Size size(Extension::kBrowserActionIconMaxSize,
    269                  Extension::kBrowserActionIconMaxSize);
    270   extension->SetCachedImage(
    271       extension->GetResource(extension->browser_action()->default_icon_path()),
    272       bitmap,
    273       size);
    274 
    275   LOG(INFO) << "Disabling extension\n" << std::flush;
    276   DisableExtension(extension->id());
    277   LOG(INFO) << "Enabling extension\n" << std::flush;
    278   EnableExtension(extension->id());
    279   LOG(INFO) << "Test ending\n" << std::flush;
    280 }
    281