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 "base/command_line.h" 6#include "base/strings/string_util.h" 7#include "chrome/app/chrome_command_ids.h" 8#include "chrome/browser/chrome_notification_types.h" 9#include "chrome/browser/extensions/extension_browsertest.h" 10#include "chrome/browser/extensions/extension_service.h" 11#include "chrome/browser/infobars/infobar_service.h" 12#include "chrome/browser/profiles/profile.h" 13#include "chrome/browser/themes/theme_service.h" 14#include "chrome/browser/themes/theme_service_factory.h" 15#include "chrome/browser/ui/browser.h" 16#include "chrome/browser/ui/browser_commands.h" 17#include "chrome/browser/ui/browser_finder.h" 18#include "chrome/browser/ui/tabs/tab_strip_model.h" 19#include "chrome/browser/ui/webui/ntp/new_tab_ui.h" 20#include "chrome/common/extensions/extension_constants.h" 21#include "chrome/common/url_constants.h" 22#include "chrome/test/base/test_switches.h" 23#include "chrome/test/base/ui_test_utils.h" 24#include "components/infobars/core/confirm_infobar_delegate.h" 25#include "components/infobars/core/infobar.h" 26#include "content/public/browser/web_contents.h" 27#include "content/public/test/browser_test_utils.h" 28#include "extensions/browser/app_sorting.h" 29#include "extensions/browser/extension_prefs.h" 30#include "extensions/common/id_util.h" 31 32using content::WebContents; 33using extensions::AppSorting; 34using extensions::Extension; 35 36class ExtensionInstallUIBrowserTest : public ExtensionBrowserTest { 37 public: 38 // Checks that a theme info bar is currently visible and issues an undo to 39 // revert to the previous theme. 40 void VerifyThemeInfoBarAndUndoInstall() { 41 WebContents* web_contents = 42 browser()->tab_strip_model()->GetActiveWebContents(); 43 ASSERT_TRUE(web_contents); 44 InfoBarService* infobar_service = 45 InfoBarService::FromWebContents(web_contents); 46 ASSERT_EQ(1U, infobar_service->infobar_count()); 47 ConfirmInfoBarDelegate* delegate = 48 infobar_service->infobar_at(0)->delegate()->AsConfirmInfoBarDelegate(); 49 ASSERT_TRUE(delegate); 50 delegate->Cancel(); 51 ASSERT_EQ(0U, infobar_service->infobar_count()); 52 } 53 54 // Install the given theme from the data dir and verify expected name. 55 void InstallThemeAndVerify(const char* theme_name, 56 const std::string& expected_name) { 57 // If there is already a theme installed, the current theme should be 58 // disabled and the new one installed + enabled. 59 int expected_change = GetTheme() ? 0 : 1; 60 const base::FilePath theme_path = test_data_dir_.AppendASCII(theme_name); 61 ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(theme_path, expected_change, 62 browser())); 63 const Extension* theme = GetTheme(); 64 ASSERT_TRUE(theme); 65 ASSERT_EQ(theme->name(), expected_name); 66 } 67 68 const Extension* GetTheme() const { 69 return ThemeServiceFactory::GetThemeForProfile(browser()->profile()); 70 } 71}; 72 73#if defined(OS_LINUX) 74// Fails consistently on bot chromium.chromiumos \ Linux. 75// See: http://crbug.com/120647. 76#define MAYBE_TestThemeInstallUndoResetsToDefault DISABLED_TestThemeInstallUndoResetsToDefault 77#else 78#define MAYBE_TestThemeInstallUndoResetsToDefault TestThemeInstallUndoResetsToDefault 79#endif 80 81IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest, 82 MAYBE_TestThemeInstallUndoResetsToDefault) { 83#if defined(OS_WIN) && defined(USE_ASH) 84 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 85 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 86 return; 87#endif 88 89 // Install theme once and undo to verify we go back to default theme. 90 base::FilePath theme_crx = PackExtension(test_data_dir_.AppendASCII("theme")); 91 ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(theme_crx, 1, browser())); 92 const Extension* theme = GetTheme(); 93 ASSERT_TRUE(theme); 94 std::string theme_id = theme->id(); 95 VerifyThemeInfoBarAndUndoInstall(); 96 ASSERT_EQ(NULL, GetTheme()); 97 98 // Set the same theme twice and undo to verify we go back to default theme. 99 ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(theme_crx, 0, browser())); 100 theme = GetTheme(); 101 ASSERT_TRUE(theme); 102 ASSERT_EQ(theme_id, theme->id()); 103 ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(theme_crx, 0, browser())); 104 theme = GetTheme(); 105 ASSERT_TRUE(theme); 106 ASSERT_EQ(theme_id, theme->id()); 107 VerifyThemeInfoBarAndUndoInstall(); 108 ASSERT_EQ(NULL, GetTheme()); 109} 110 111IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest, 112 TestThemeInstallUndoResetsToPreviousTheme) { 113#if defined(OS_WIN) && defined(USE_ASH) 114 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 115 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 116 return; 117#endif 118 119 // Install first theme. 120 InstallThemeAndVerify("theme", "camo theme"); 121 const Extension* theme = GetTheme(); 122 std::string theme_id = theme->id(); 123 124 // Then install second theme. 125 InstallThemeAndVerify("theme2", "snowflake theme"); 126 const Extension* theme2 = GetTheme(); 127 EXPECT_FALSE(theme_id == theme2->id()); 128 129 // Undo second theme will revert to first theme. 130 VerifyThemeInfoBarAndUndoInstall(); 131 EXPECT_EQ(theme, GetTheme()); 132} 133 134IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest, 135 TestThemeReset) { 136 InstallThemeAndVerify("theme", "camo theme"); 137 138 // Reset to default theme. 139 ThemeServiceFactory::GetForProfile(browser()->profile())->UseDefaultTheme(); 140 ASSERT_FALSE(GetTheme()); 141} 142 143IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest, 144 TestInstallThemeInFullScreen) { 145 EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_FULLSCREEN)); 146 InstallThemeAndVerify("theme", "camo theme"); 147} 148 149// TODO(samarth): remove along with NTP4 code. 150IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest, 151 DISABLED_AppInstallConfirmation) { 152 int num_tabs = browser()->tab_strip_model()->count(); 153 154 base::FilePath app_dir = test_data_dir_.AppendASCII("app"); 155 ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1, browser())); 156 157 if (NewTabUI::ShouldShowApps()) { 158 EXPECT_EQ(num_tabs + 1, browser()->tab_strip_model()->count()); 159 WebContents* web_contents = 160 browser()->tab_strip_model()->GetActiveWebContents(); 161 ASSERT_TRUE(web_contents); 162 EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(), 163 "chrome://newtab/", false)); 164 } else { 165 // TODO(xiyuan): Figure out how to test extension installed bubble? 166 } 167} 168 169// TODO(samarth): remove along with NTP4 code. 170IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest, 171 DISABLED_AppInstallConfirmation_Incognito) { 172 Browser* incognito_browser = CreateIncognitoBrowser(); 173 174 int num_incognito_tabs = incognito_browser->tab_strip_model()->count(); 175 int num_normal_tabs = browser()->tab_strip_model()->count(); 176 177 base::FilePath app_dir = test_data_dir_.AppendASCII("app"); 178 ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1, 179 incognito_browser)); 180 181 EXPECT_EQ(num_incognito_tabs, 182 incognito_browser->tab_strip_model()->count()); 183 if (NewTabUI::ShouldShowApps()) { 184 EXPECT_EQ(num_normal_tabs + 1, browser()->tab_strip_model()->count()); 185 WebContents* web_contents = 186 browser()->tab_strip_model()->GetActiveWebContents(); 187 ASSERT_TRUE(web_contents); 188 EXPECT_TRUE(StartsWithASCII(web_contents->GetURL().spec(), 189 "chrome://newtab/", false)); 190 } else { 191 // TODO(xiyuan): Figure out how to test extension installed bubble? 192 } 193} 194 195class NewTabUISortingBrowserTest : public ExtensionInstallUIBrowserTest, 196 public content::NotificationObserver { 197 public: 198 NewTabUISortingBrowserTest() {} 199 200 virtual void Observe(int type, 201 const content::NotificationSource& source, 202 const content::NotificationDetails& details) OVERRIDE { 203 if (type != chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED) { 204 observer_->Observe(type, source, details); 205 return; 206 } 207 const std::string* id = content::Details<const std::string>(details).ptr(); 208 EXPECT_TRUE(id); 209 last_reordered_extension_id_ = *id; 210 } 211 212 protected: 213 std::string last_reordered_extension_id_; 214 content::NotificationRegistrar registrar_; 215 216 private: 217 DISALLOW_COPY_AND_ASSIGN(NewTabUISortingBrowserTest); 218}; 219 220// TODO(samarth): remove along with NTP4 code. 221IN_PROC_BROWSER_TEST_F(NewTabUISortingBrowserTest, 222 DISABLED_ReorderDuringInstall) { 223 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); 224 ExtensionService* service = extensions::ExtensionSystem::Get( 225 browser()->profile())->extension_service(); 226 base::FilePath app_dir = test_data_dir_.AppendASCII("app"); 227 const std::string app_id = extensions::id_util::GenerateIdForPath(app_dir); 228 229 const extensions::Extension* webstore_extension = 230 service->GetInstalledExtension(extension_misc::kWebStoreAppId); 231 EXPECT_TRUE(webstore_extension); 232 AppSorting* sorting = 233 extensions::ExtensionPrefs::Get(browser()->profile())->app_sorting(); 234 235 // Register for notifications in the same way as AppLauncherHandler. 236 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, 237 content::Source<AppSorting>(sorting)); 238 // ExtensionAppItem calls this when an app install starts. 239 sorting->EnsureValidOrdinals(app_id, syncer::StringOrdinal()); 240 // Vefify the app is not actually installed yet. 241 EXPECT_FALSE(service->GetInstalledExtension(app_id)); 242 // Move the test app from the end to be before the web store. 243 sorting->OnExtensionMoved( 244 app_id, std::string(), extension_misc::kWebStoreAppId); 245 EXPECT_EQ(app_id, last_reordered_extension_id_); 246 247 // Now install the app. 248 const extensions::Extension* test_app = LoadExtension(app_dir); 249 ASSERT_TRUE(test_app); 250 EXPECT_TRUE(service->GetInstalledExtension(app_id)); 251 EXPECT_EQ(app_id, test_app->id()); 252} 253