Home | History | Annotate | Download | only in extensions
      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 <string>
      6 
      7 #include "base/command_line.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "chrome/browser/extensions/active_script_controller.h"
     11 #include "chrome/browser/extensions/extension_action.h"
     12 #include "chrome/browser/extensions/extension_action_manager.h"
     13 #include "chrome/browser/extensions/extension_service.h"
     14 #include "chrome/browser/extensions/location_bar_controller.h"
     15 #include "chrome/browser/extensions/tab_helper.h"
     16 #include "chrome/browser/extensions/test_extension_system.h"
     17 #include "chrome/browser/sessions/session_tab_helper.h"
     18 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
     19 #include "chrome/test/base/testing_profile.h"
     20 #include "components/crx_file/id_util.h"
     21 #include "extensions/common/extension.h"
     22 #include "extensions/common/extension_builder.h"
     23 #include "extensions/common/feature_switch.h"
     24 #include "extensions/common/value_builder.h"
     25 
     26 #if defined(OS_CHROMEOS)
     27 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
     28 #include "chrome/browser/chromeos/settings/cros_settings.h"
     29 #include "chrome/browser/chromeos/settings/device_settings_service.h"
     30 #endif
     31 
     32 namespace extensions {
     33 namespace {
     34 
     35 class LocationBarControllerUnitTest : public ChromeRenderViewHostTestHarness {
     36  protected:
     37   virtual void SetUp() OVERRIDE {
     38     active_script_override_.reset(new FeatureSwitch::ScopedOverride(
     39         FeatureSwitch::scripts_require_action(), true));
     40 
     41     ChromeRenderViewHostTestHarness::SetUp();
     42 #if defined OS_CHROMEOS
     43   test_user_manager_.reset(new chromeos::ScopedTestUserManager());
     44 #endif
     45     TabHelper::CreateForWebContents(web_contents());
     46     // Create an ExtensionService so the LocationBarController can find its
     47     // extensions.
     48     CommandLine command_line(CommandLine::NO_PROGRAM);
     49     Profile* profile =
     50         Profile::FromBrowserContext(web_contents()->GetBrowserContext());
     51     extension_service_ = static_cast<TestExtensionSystem*>(
     52         ExtensionSystem::Get(profile))->CreateExtensionService(
     53             &command_line, base::FilePath(), false);
     54   }
     55 
     56   virtual void TearDown() OVERRIDE {
     57 #if defined OS_CHROMEOS
     58     test_user_manager_.reset();
     59 #endif
     60     ChromeRenderViewHostTestHarness::TearDown();
     61   }
     62 
     63   int tab_id() {
     64     return SessionTabHelper::IdForTab(web_contents());
     65   }
     66 
     67   const Extension* AddExtension(bool has_page_actions,
     68                                 const std::string& name) {
     69     DictionaryBuilder manifest;
     70     manifest.Set("name", name)
     71             .Set("version", "1.0.0")
     72             .Set("manifest_version", 2)
     73             .Set("permissions", ListBuilder().Append("tabs"));
     74     if (has_page_actions) {
     75       manifest.Set("page_action", DictionaryBuilder()
     76               .Set("default_title", "Hello"));
     77     }
     78     scoped_refptr<const Extension> extension =
     79         ExtensionBuilder().SetManifest(manifest.Pass())
     80                           .SetID(crx_file::id_util::GenerateId(name))
     81                           .Build();
     82     extension_service_->AddExtension(extension.get());
     83     return extension.get();
     84   }
     85 
     86   ExtensionService* extension_service_;
     87 
     88  private:
     89 #if defined OS_CHROMEOS
     90   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
     91   chromeos::ScopedTestCrosSettings test_cros_settings_;
     92   scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
     93 #endif
     94 
     95   // Since we also test that we show page actions for pending script requests,
     96   // we need to enable that feature.
     97   scoped_ptr<FeatureSwitch::ScopedOverride> active_script_override_;
     98 };
     99 
    100 // Test that the location bar gets the proper current actions.
    101 TEST_F(LocationBarControllerUnitTest, LocationBarDisplaysPageActions) {
    102   // Load up two extensions, one with a page action and one without.
    103   const Extension* page_action = AddExtension(true, "page_actions");
    104   const Extension* no_action = AddExtension(false, "no_actions");
    105 
    106   TabHelper* tab_helper = TabHelper::FromWebContents(web_contents());
    107   ASSERT_TRUE(tab_helper);
    108   LocationBarController* controller = tab_helper->location_bar_controller();
    109   ASSERT_TRUE(controller);
    110 
    111   // There should only be one action - the action for the extension with a
    112   // page action.
    113   std::vector<ExtensionAction*> current_actions =
    114       controller->GetCurrentActions();
    115   ASSERT_EQ(1u, current_actions.size());
    116   EXPECT_EQ(page_action->id(), current_actions[0]->extension_id());
    117 
    118   // If we request a script injection, then the location bar controller should
    119   // also show a page action for that extension.
    120   ActiveScriptController* active_script_controller =
    121       ActiveScriptController::GetForWebContents(web_contents());
    122   ASSERT_TRUE(active_script_controller);
    123   active_script_controller->RequestScriptInjectionForTesting(no_action,
    124                                                              base::Closure());
    125   current_actions = controller->GetCurrentActions();
    126   ASSERT_EQ(2u, current_actions.size());
    127   // Check that each extension is present in the vector.
    128   EXPECT_TRUE(current_actions[0]->extension_id() == no_action->id() ||
    129               current_actions[1]->extension_id() == no_action->id());
    130   EXPECT_TRUE(current_actions[0]->extension_id() == page_action->id() ||
    131               current_actions[1]->extension_id() == page_action->id());
    132 
    133   // If we request a script injection for an extension that already has a
    134   // page action, only one action should be visible.
    135   active_script_controller->RequestScriptInjectionForTesting(page_action,
    136                                                              base::Closure());
    137   current_actions = controller->GetCurrentActions();
    138   ASSERT_EQ(2u, current_actions.size());
    139   EXPECT_TRUE(current_actions[0]->extension_id() == no_action->id() ||
    140               current_actions[1]->extension_id() == no_action->id());
    141   EXPECT_TRUE(current_actions[0]->extension_id() == page_action->id() ||
    142               current_actions[1]->extension_id() == page_action->id());
    143 
    144   // Navigating away means that only page actions are shown again.
    145   NavigateAndCommit(GURL("http://google.com"));
    146   current_actions = controller->GetCurrentActions();
    147   ASSERT_EQ(1u, current_actions.size());
    148   EXPECT_EQ(page_action->id(), current_actions[0]->extension_id());
    149 }
    150 
    151 // Test that navigating clears all state in a page action.
    152 TEST_F(LocationBarControllerUnitTest, NavigationClearsState) {
    153   const Extension* extension = AddExtension(true, "page_actions");
    154 
    155   NavigateAndCommit(GURL("http://www.google.com"));
    156 
    157   ExtensionAction& page_action =
    158       *ExtensionActionManager::Get(profile())->GetPageAction(*extension);
    159   page_action.SetTitle(tab_id(), "Goodbye");
    160   page_action.SetPopupUrl(tab_id(), extension->GetResourceURL("popup.html"));
    161 
    162   EXPECT_EQ("Goodbye", page_action.GetTitle(tab_id()));
    163   EXPECT_EQ(extension->GetResourceURL("popup.html"),
    164             page_action.GetPopupUrl(tab_id()));
    165 
    166   // Within-page navigation should keep the settings.
    167   NavigateAndCommit(GURL("http://www.google.com/#hash"));
    168 
    169   EXPECT_EQ("Goodbye", page_action.GetTitle(tab_id()));
    170   EXPECT_EQ(extension->GetResourceURL("popup.html"),
    171             page_action.GetPopupUrl(tab_id()));
    172 
    173   // Should discard the settings, and go back to the defaults.
    174   NavigateAndCommit(GURL("http://www.yahoo.com"));
    175 
    176   EXPECT_EQ("Hello", page_action.GetTitle(tab_id()));
    177   EXPECT_EQ(GURL(), page_action.GetPopupUrl(tab_id()));
    178 }
    179 
    180 }  // namespace
    181 }  // namespace extensions
    182