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