Home | History | Annotate | Download | only in extensions
      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 "build/build_config.h"
      6 
      7 #if defined(TOOLKIT_GTK)
      8 #include <gtk/gtk.h>
      9 #endif
     10 
     11 #include "chrome/browser/extensions/browser_action_test_util.h"
     12 #include "chrome/browser/extensions/extension_apitest.h"
     13 #include "chrome/browser/extensions/extension_browser_event_router.h"
     14 #include "chrome/browser/extensions/extension_service.h"
     15 #include "chrome/browser/extensions/extension_tabs_module.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/ui/browser.h"
     18 #include "chrome/browser/ui/browser_window.h"
     19 #include "chrome/common/extensions/extension_action.h"
     20 #include "chrome/common/url_constants.h"
     21 #include "chrome/test/ui_test_utils.h"
     22 #include "content/browser/tab_contents/tab_contents.h"
     23 #include "ui/gfx/rect.h"
     24 #include "ui/gfx/size.h"
     25 
     26 class BrowserActionApiTest : public ExtensionApiTest {
     27  public:
     28   BrowserActionApiTest() {}
     29   virtual ~BrowserActionApiTest() {}
     30 
     31  protected:
     32   BrowserActionTestUtil GetBrowserActionsBar() {
     33     return BrowserActionTestUtil(browser());
     34   }
     35 
     36   bool OpenPopup(int index) {
     37     ResultCatcher catcher;
     38     GetBrowserActionsBar().Press(index);
     39     ui_test_utils::WaitForNotification(
     40         NotificationType::EXTENSION_POPUP_VIEW_READY);
     41     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
     42     return GetBrowserActionsBar().HasPopup();
     43   }
     44 };
     45 
     46 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Basic) {
     47   ASSERT_TRUE(test_server()->Start());
     48   ASSERT_TRUE(RunExtensionTest("browser_action/basics")) << message_;
     49   const Extension* extension = GetSingleLoadedExtension();
     50   ASSERT_TRUE(extension) << message_;
     51 
     52   // Test that there is a browser action in the toolbar.
     53   ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions());
     54 
     55   // Tell the extension to update the browser action state.
     56   ResultCatcher catcher;
     57   ui_test_utils::NavigateToURL(browser(),
     58       GURL(extension->GetResourceURL("update.html")));
     59   ASSERT_TRUE(catcher.GetNextResult());
     60 
     61   // Test that we received the changes.
     62   ExtensionAction* action = extension->browser_action();
     63   ASSERT_EQ("Modified", action->GetTitle(ExtensionAction::kDefaultTabId));
     64   ASSERT_EQ("badge", action->GetBadgeText(ExtensionAction::kDefaultTabId));
     65   ASSERT_EQ(SkColorSetARGB(255, 255, 255, 255),
     66             action->GetBadgeBackgroundColor(ExtensionAction::kDefaultTabId));
     67 
     68   // Simulate the browser action being clicked.
     69   ui_test_utils::NavigateToURL(browser(),
     70       test_server()->GetURL("files/extensions/test_file.txt"));
     71 
     72   ExtensionService* service = browser()->profile()->GetExtensionService();
     73   service->browser_event_router()->BrowserActionExecuted(
     74       browser()->profile(), action->extension_id(), browser());
     75 
     76   // Verify the command worked.
     77   TabContents* tab = browser()->GetSelectedTabContents();
     78   bool result = false;
     79   ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
     80       tab->render_view_host(), L"",
     81       L"setInterval(function(){"
     82       L"  if(document.body.bgColor == 'red'){"
     83       L"    window.domAutomationController.send(true)}}, 100)",
     84       &result));
     85   ASSERT_TRUE(result);
     86 }
     87 
     88 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DynamicBrowserAction) {
     89   ASSERT_TRUE(RunExtensionTest("browser_action/no_icon")) << message_;
     90   const Extension* extension = GetSingleLoadedExtension();
     91   ASSERT_TRUE(extension) << message_;
     92 
     93   // Test that there is a browser action in the toolbar and that it has no icon.
     94   ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions());
     95   EXPECT_FALSE(GetBrowserActionsBar().HasIcon(0));
     96 
     97   // Tell the extension to update the icon using setIcon({imageData:...}).
     98   ResultCatcher catcher;
     99   ui_test_utils::NavigateToURL(browser(),
    100       GURL(extension->GetResourceURL("update.html")));
    101   ASSERT_TRUE(catcher.GetNextResult());
    102 
    103   // Test that we received the changes.
    104   EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0));
    105 
    106   // Tell the extension to update using setIcon({path:...});
    107   ui_test_utils::NavigateToURL(browser(),
    108       GURL(extension->GetResourceURL("update2.html")));
    109   ASSERT_TRUE(catcher.GetNextResult());
    110 
    111   // Test that we received the changes.
    112   EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0));
    113 
    114   // TODO(aa): Would be nice here to actually compare that the pixels change.
    115 }
    116 
    117 // This test is flaky as per http://crbug.com/74557.
    118 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest,
    119                        FLAKY_TabSpecificBrowserActionState) {
    120   ASSERT_TRUE(RunExtensionTest("browser_action/tab_specific_state")) <<
    121       message_;
    122   const Extension* extension = GetSingleLoadedExtension();
    123   ASSERT_TRUE(extension) << message_;
    124 
    125   // Test that there is a browser action in the toolbar and that it has an icon.
    126   ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions());
    127   EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0));
    128 
    129   // Execute the action, its title should change.
    130   ResultCatcher catcher;
    131   GetBrowserActionsBar().Press(0);
    132   ASSERT_TRUE(catcher.GetNextResult());
    133   EXPECT_EQ("Showing icon 2", GetBrowserActionsBar().GetTooltip(0));
    134 
    135   // Open a new tab, the title should go back.
    136   browser()->NewTab();
    137   EXPECT_EQ("hi!", GetBrowserActionsBar().GetTooltip(0));
    138 
    139   // Go back to first tab, changed title should reappear.
    140   browser()->ActivateTabAt(0, true);
    141   EXPECT_EQ("Showing icon 2", GetBrowserActionsBar().GetTooltip(0));
    142 
    143   // Reload that tab, default title should come back.
    144   ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
    145   EXPECT_EQ("hi!", GetBrowserActionsBar().GetTooltip(0));
    146 }
    147 
    148 // http://code.google.com/p/chromium/issues/detail?id=70829
    149 // Only mac is okay.
    150 #if !defined(OS_MACOSX)
    151 #define MAYBE_BrowserActionPopup DISABLED_BrowserActionPopup
    152 #else
    153 #define MAYBE_BrowserActionPopup BrowserActionPopup
    154 #endif
    155 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, MAYBE_BrowserActionPopup) {
    156   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    157       "browser_action/popup")));
    158   BrowserActionTestUtil actions_bar = GetBrowserActionsBar();
    159   const Extension* extension = GetSingleLoadedExtension();
    160   ASSERT_TRUE(extension) << message_;
    161 
    162   // The extension's popup's size grows by |growFactor| each click.
    163   const int growFactor = 500;
    164   gfx::Size minSize = BrowserActionTestUtil::GetMinPopupSize();
    165   gfx::Size middleSize = gfx::Size(growFactor, growFactor);
    166   gfx::Size maxSize = BrowserActionTestUtil::GetMaxPopupSize();
    167 
    168   // Ensure that two clicks will exceed the maximum allowed size.
    169   ASSERT_GT(minSize.height() + growFactor * 2, maxSize.height());
    170   ASSERT_GT(minSize.width() + growFactor * 2, maxSize.width());
    171 
    172   // Simulate a click on the browser action and verify the size of the resulting
    173   // popup.  The first one tries to be 0x0, so it should be the min values.
    174   ASSERT_TRUE(OpenPopup(0));
    175   EXPECT_EQ(minSize, actions_bar.GetPopupBounds().size());
    176   EXPECT_TRUE(actions_bar.HidePopup());
    177 
    178   ASSERT_TRUE(OpenPopup(0));
    179   EXPECT_EQ(middleSize, actions_bar.GetPopupBounds().size());
    180   EXPECT_TRUE(actions_bar.HidePopup());
    181 
    182   // One more time, but this time it should be constrained by the max values.
    183   ASSERT_TRUE(OpenPopup(0));
    184   EXPECT_EQ(maxSize, actions_bar.GetPopupBounds().size());
    185   EXPECT_TRUE(actions_bar.HidePopup());
    186 }
    187 
    188 // Test that calling chrome.browserAction.setPopup() can enable and change
    189 // a popup.
    190 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionAddPopup) {
    191   ASSERT_TRUE(RunExtensionTest("browser_action/add_popup")) << message_;
    192   const Extension* extension = GetSingleLoadedExtension();
    193   ASSERT_TRUE(extension) << message_;
    194 
    195   int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents());
    196 
    197   ExtensionAction* browser_action = extension->browser_action();
    198   ASSERT_TRUE(browser_action)
    199       << "Browser action test extension should have a browser action.";
    200 
    201   ASSERT_FALSE(browser_action->HasPopup(tab_id));
    202   ASSERT_FALSE(browser_action->HasPopup(ExtensionAction::kDefaultTabId));
    203 
    204   // Simulate a click on the browser action icon.  The onClicked handler
    205   // will add a popup.
    206   {
    207     ResultCatcher catcher;
    208     GetBrowserActionsBar().Press(0);
    209     ASSERT_TRUE(catcher.GetNextResult());
    210   }
    211 
    212   // The call to setPopup in background.html set a tab id, so the
    213   // current tab's setting should have changed, but the default setting
    214   // should not have changed.
    215   ASSERT_TRUE(browser_action->HasPopup(tab_id))
    216       << "Clicking on the browser action should have caused a popup to "
    217       << "be added.";
    218   ASSERT_FALSE(browser_action->HasPopup(ExtensionAction::kDefaultTabId))
    219       << "Clicking on the browser action should not have set a default "
    220       << "popup.";
    221 
    222   ASSERT_STREQ("/a_popup.html",
    223                browser_action->GetPopupUrl(tab_id).path().c_str());
    224 
    225   // Now change the popup from a_popup.html to another_popup.html by loading
    226   // a page which removes the popup using chrome.browserAction.setPopup().
    227   {
    228     ResultCatcher catcher;
    229     ui_test_utils::NavigateToURL(
    230         browser(),
    231         GURL(extension->GetResourceURL("change_popup.html")));
    232     ASSERT_TRUE(catcher.GetNextResult());
    233   }
    234 
    235   // The call to setPopup in change_popup.html did not use a tab id,
    236   // so the default setting should have changed as well as the current tab.
    237   ASSERT_TRUE(browser_action->HasPopup(tab_id));
    238   ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId));
    239   ASSERT_STREQ("/another_popup.html",
    240                browser_action->GetPopupUrl(tab_id).path().c_str());
    241 }
    242 
    243 // Test that calling chrome.browserAction.setPopup() can remove a popup.
    244 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionRemovePopup) {
    245   // Load the extension, which has a browser action with a default popup.
    246   ASSERT_TRUE(RunExtensionTest("browser_action/remove_popup")) << message_;
    247   const Extension* extension = GetSingleLoadedExtension();
    248   ASSERT_TRUE(extension) << message_;
    249 
    250   int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents());
    251 
    252   ExtensionAction* browser_action = extension->browser_action();
    253   ASSERT_TRUE(browser_action)
    254       << "Browser action test extension should have a browser action.";
    255 
    256   ASSERT_TRUE(browser_action->HasPopup(tab_id))
    257       << "Expect a browser action popup before the test removes it.";
    258   ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId))
    259       << "Expect a browser action popup is the default for all tabs.";
    260 
    261   // Load a page which removes the popup using chrome.browserAction.setPopup().
    262   {
    263     ResultCatcher catcher;
    264     ui_test_utils::NavigateToURL(
    265         browser(),
    266         GURL(extension->GetResourceURL("remove_popup.html")));
    267     ASSERT_TRUE(catcher.GetNextResult());
    268   }
    269 
    270   ASSERT_FALSE(browser_action->HasPopup(tab_id))
    271       << "Browser action popup should have been removed.";
    272   ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId))
    273       << "Browser action popup default should not be changed by setting "
    274       << "a specific tab id.";
    275 }
    276 
    277 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoBasic) {
    278   ASSERT_TRUE(test_server()->Start());
    279 
    280   ASSERT_TRUE(RunExtensionTest("browser_action/basics")) << message_;
    281   const Extension* extension = GetSingleLoadedExtension();
    282   ASSERT_TRUE(extension) << message_;
    283 
    284   // Test that there is a browser action in the toolbar.
    285   ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions());
    286 
    287   // Open an incognito window and test that the browser action isn't there by
    288   // default.
    289   Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
    290   Browser* incognito_browser = Browser::Create(incognito_profile);
    291 
    292   ASSERT_EQ(0,
    293             BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions());
    294 
    295   // Now enable the extension in incognito mode, and test that the browser
    296   // action shows up. Note that we don't update the existing window at the
    297   // moment, so we just create a new one.
    298   browser()->profile()->GetExtensionService()->extension_prefs()->
    299       SetIsIncognitoEnabled(extension->id(), true);
    300 
    301   incognito_browser->CloseWindow();
    302   incognito_browser = Browser::Create(incognito_profile);
    303   ASSERT_EQ(1,
    304             BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions());
    305 
    306   // TODO(mpcomplete): simulate a click and have it do the right thing in
    307   // incognito.
    308 }
    309 
    310 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoDragging) {
    311   ExtensionService* service = browser()->profile()->GetExtensionService();
    312 
    313   // The tooltips for each respective browser action.
    314   const char kTooltipA[] = "Make this page red";
    315   const char kTooltipB[] = "grow";
    316   const char kTooltipC[] = "Test setPopup()";
    317 
    318   const size_t size_before = service->extensions()->size();
    319 
    320   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    321       "browser_action/basics")));
    322   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    323       "browser_action/popup")));
    324   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    325       "browser_action/add_popup")));
    326 
    327   // Test that there are 3 browser actions in the toolbar.
    328   ASSERT_EQ(size_before + 3, service->extensions()->size());
    329   ASSERT_EQ(3, GetBrowserActionsBar().NumberOfBrowserActions());
    330 
    331   // Now enable 2 of the extensions in incognito mode, and test that the browser
    332   // actions show up.
    333   service->extension_prefs()->SetIsIncognitoEnabled(
    334       service->extensions()->at(size_before)->id(), true);
    335   service->extension_prefs()->SetIsIncognitoEnabled(
    336       service->extensions()->at(size_before + 2)->id(), true);
    337 
    338   Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
    339   Browser* incognito_browser = Browser::Create(incognito_profile);
    340   BrowserActionTestUtil incognito_bar(incognito_browser);
    341 
    342   // Navigate just to have a tab in this window, otherwise wonky things happen.
    343   ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
    344                                      GURL(chrome::kChromeUIExtensionsURL));
    345 
    346   ASSERT_EQ(2, incognito_bar.NumberOfBrowserActions());
    347 
    348   // Ensure that the browser actions are in the right order (ABC).
    349   EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(0));
    350   EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(1));
    351   EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(2));
    352 
    353   EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(0));
    354   EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(1));
    355 
    356   // Now rearrange them and ensure that they are rearranged correctly in both
    357   // regular and incognito mode.
    358 
    359   // ABC -> CAB
    360   service->toolbar_model()->MoveBrowserAction(
    361       service->extensions()->at(size_before + 2), 0);
    362 
    363   EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0));
    364   EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(1));
    365   EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(2));
    366 
    367   EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(0));
    368   EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(1));
    369 
    370   // CAB -> CBA
    371   service->toolbar_model()->MoveBrowserAction(
    372       service->extensions()->at(size_before + 1), 1);
    373 
    374   EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0));
    375   EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(1));
    376   EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(2));
    377 
    378   EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(0));
    379   EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(1));
    380 }
    381