1 // Copyright 2014 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/memory/scoped_ptr.h" 6 #include "base/metrics/field_trial.h" 7 #include "base/prefs/pref_service.h" 8 #include "chrome/browser/browser_process.h" 9 #include "chrome/browser/extensions/extension_service_test_base.h" 10 #include "chrome/browser/extensions/test_extension_service.h" 11 #include "chrome/browser/search/hotword_service.h" 12 #include "chrome/browser/search/hotword_service_factory.h" 13 #include "chrome/common/extensions/extension_constants.h" 14 #include "chrome/common/pref_names.h" 15 #include "chrome/test/base/testing_profile.h" 16 #include "content/public/test/test_browser_thread_bundle.h" 17 #include "extensions/browser/extension_system.h" 18 #include "extensions/common/extension.h" 19 #include "extensions/common/extension_builder.h" 20 #include "extensions/common/manifest.h" 21 #include "extensions/common/one_shot_event.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 namespace { 25 26 class MockHotwordService : public HotwordService { 27 public: 28 explicit MockHotwordService(Profile* profile) 29 : HotwordService(profile), 30 uninstall_count_(0) { 31 } 32 33 virtual bool UninstallHotwordExtension( 34 ExtensionService* extension_service) OVERRIDE { 35 uninstall_count_++; 36 return HotwordService::UninstallHotwordExtension(extension_service); 37 } 38 39 virtual void InstallHotwordExtensionFromWebstore() OVERRIDE{ 40 scoped_ptr<base::DictionaryValue> manifest = 41 extensions::DictionaryBuilder() 42 .Set("name", "Hotword Test Extension") 43 .Set("version", "1.0") 44 .Set("manifest_version", 2) 45 .Build(); 46 scoped_refptr<extensions::Extension> extension = 47 extensions::ExtensionBuilder().SetManifest(manifest.Pass()) 48 .AddFlags(extensions::Extension::FROM_WEBSTORE 49 | extensions::Extension::WAS_INSTALLED_BY_DEFAULT) 50 .SetID(extension_misc::kHotwordExtensionId) 51 .SetLocation(extensions::Manifest::EXTERNAL_COMPONENT) 52 .Build(); 53 ASSERT_TRUE(extension.get()); 54 service_->OnExtensionInstalled(extension, syncer::StringOrdinal()); 55 } 56 57 58 int uninstall_count() { return uninstall_count_; } 59 60 void SetExtensionService(ExtensionService* service) { service_ = service; } 61 62 ExtensionService* extension_service() { return service_; } 63 64 private: 65 ExtensionService* service_; 66 int uninstall_count_; 67 }; 68 69 KeyedService* BuildMockHotwordService(content::BrowserContext* context) { 70 return new MockHotwordService(static_cast<Profile*>(context)); 71 } 72 73 } // namespace 74 75 class HotwordServiceTest : public extensions::ExtensionServiceTestBase { 76 protected: 77 HotwordServiceTest() : field_trial_list_(NULL) {} 78 virtual ~HotwordServiceTest() {} 79 80 void SetApplicationLocale(Profile* profile, const std::string& new_locale) { 81 #if defined(OS_CHROMEOS) 82 // On ChromeOS locale is per-profile. 83 profile->GetPrefs()->SetString(prefs::kApplicationLocale, new_locale); 84 #else 85 g_browser_process->SetApplicationLocale(new_locale); 86 #endif 87 } 88 89 private: 90 base::FieldTrialList field_trial_list_; 91 }; 92 93 TEST_F(HotwordServiceTest, IsHotwordAllowedBadFieldTrial) { 94 TestingProfile::Builder profile_builder; 95 TestingProfile::Builder otr_profile_builder; 96 otr_profile_builder.SetIncognito(); 97 scoped_ptr<TestingProfile> profile = profile_builder.Build(); 98 scoped_ptr<TestingProfile> otr_profile = otr_profile_builder.Build(); 99 100 HotwordServiceFactory* hotword_service_factory = 101 HotwordServiceFactory::GetInstance(); 102 103 // Check that the service exists so that a NULL service be ruled out in 104 // following tests. 105 HotwordService* hotword_service = 106 hotword_service_factory->GetForProfile(profile.get()); 107 EXPECT_TRUE(hotword_service != NULL); 108 109 // When the field trial is empty or Disabled, it should not be allowed. 110 std::string group = base::FieldTrialList::FindFullName( 111 hotword_internal::kHotwordFieldTrialName); 112 EXPECT_TRUE(group.empty()); 113 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 114 115 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 116 hotword_internal::kHotwordFieldTrialName, 117 hotword_internal::kHotwordFieldTrialDisabledGroupName)); 118 group = base::FieldTrialList::FindFullName( 119 hotword_internal::kHotwordFieldTrialName); 120 EXPECT_TRUE(group ==hotword_internal::kHotwordFieldTrialDisabledGroupName); 121 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 122 123 // Set a valid locale with invalid field trial to be sure it is 124 // still false. 125 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en"); 126 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 127 128 // Test that incognito returns false as well. 129 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(otr_profile.get())); 130 } 131 132 TEST_F(HotwordServiceTest, IsHotwordAllowedLocale) { 133 TestingProfile::Builder profile_builder; 134 TestingProfile::Builder otr_profile_builder; 135 otr_profile_builder.SetIncognito(); 136 scoped_ptr<TestingProfile> profile = profile_builder.Build(); 137 scoped_ptr<TestingProfile> otr_profile = otr_profile_builder.Build(); 138 139 HotwordServiceFactory* hotword_service_factory = 140 HotwordServiceFactory::GetInstance(); 141 142 // Check that the service exists so that a NULL service be ruled out in 143 // following tests. 144 HotwordService* hotword_service = 145 hotword_service_factory->GetForProfile(profile.get()); 146 EXPECT_TRUE(hotword_service != NULL); 147 148 // Set the field trial to a valid one. 149 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 150 hotword_internal::kHotwordFieldTrialName, "Good")); 151 152 // Set the language to an invalid one. 153 SetApplicationLocale(static_cast<Profile*>(profile.get()), "non-valid"); 154 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 155 156 // Now with valid locales it should be fine. 157 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en"); 158 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 159 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en-US"); 160 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 161 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en_us"); 162 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 163 SetApplicationLocale(static_cast<Profile*>(profile.get()), "de_DE"); 164 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 165 SetApplicationLocale(static_cast<Profile*>(profile.get()), "fr_fr"); 166 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 167 168 // Test that incognito even with a valid locale and valid field trial 169 // still returns false. 170 SetApplicationLocale(static_cast<Profile*>(otr_profile.get()), "en"); 171 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(otr_profile.get())); 172 } 173 174 TEST_F(HotwordServiceTest, AudioLoggingPrefSetCorrectly) { 175 TestingProfile::Builder profile_builder; 176 scoped_ptr<TestingProfile> profile = profile_builder.Build(); 177 178 HotwordServiceFactory* hotword_service_factory = 179 HotwordServiceFactory::GetInstance(); 180 HotwordService* hotword_service = 181 hotword_service_factory->GetForProfile(profile.get()); 182 EXPECT_TRUE(hotword_service != NULL); 183 184 // If it's a fresh profile, although the default value is true, 185 // it should return false if the preference has never been set. 186 EXPECT_FALSE(hotword_service->IsOptedIntoAudioLogging()); 187 } 188 189 TEST_F(HotwordServiceTest, ShouldReinstallExtension) { 190 // Set the field trial to a valid one. 191 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 192 hotword_internal::kHotwordFieldTrialName, "Install")); 193 194 InitializeEmptyExtensionService(); 195 196 HotwordServiceFactory* hotword_service_factory = 197 HotwordServiceFactory::GetInstance(); 198 199 MockHotwordService* hotword_service = static_cast<MockHotwordService*>( 200 hotword_service_factory->SetTestingFactoryAndUse( 201 profile(), BuildMockHotwordService)); 202 EXPECT_TRUE(hotword_service != NULL); 203 204 // If no locale has been set, no reason to uninstall. 205 EXPECT_FALSE(hotword_service->ShouldReinstallHotwordExtension()); 206 207 SetApplicationLocale(profile(), "en"); 208 hotword_service->SetPreviousLanguagePref(); 209 210 // Now a locale is set, but it hasn't changed. 211 EXPECT_FALSE(hotword_service->ShouldReinstallHotwordExtension()); 212 213 SetApplicationLocale(profile(), "fr_fr"); 214 215 // Now it's a different locale so it should uninstall. 216 EXPECT_TRUE(hotword_service->ShouldReinstallHotwordExtension()); 217 } 218 219 TEST_F(HotwordServiceTest, PreviousLanguageSetOnInstall) { 220 // Set the field trial to a valid one. 221 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 222 hotword_internal::kHotwordFieldTrialName, "Install")); 223 224 InitializeEmptyExtensionService(); 225 service_->Init(); 226 227 HotwordServiceFactory* hotword_service_factory = 228 HotwordServiceFactory::GetInstance(); 229 230 MockHotwordService* hotword_service = static_cast<MockHotwordService*>( 231 hotword_service_factory->SetTestingFactoryAndUse( 232 profile(), BuildMockHotwordService)); 233 EXPECT_TRUE(hotword_service != NULL); 234 hotword_service->SetExtensionService(service()); 235 236 // If no locale has been set, no reason to uninstall. 237 EXPECT_FALSE(hotword_service->ShouldReinstallHotwordExtension()); 238 239 SetApplicationLocale(profile(), "test_locale"); 240 241 hotword_service->InstallHotwordExtensionFromWebstore(); 242 base::MessageLoop::current()->RunUntilIdle(); 243 244 EXPECT_EQ("test_locale", 245 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 246 } 247 248 TEST_F(HotwordServiceTest, UninstallReinstallTriggeredCorrectly) { 249 // Set the field trial to a valid one. 250 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 251 hotword_internal::kHotwordFieldTrialName, "Install")); 252 253 InitializeEmptyExtensionService(); 254 service_->Init(); 255 256 HotwordServiceFactory* hotword_service_factory = 257 HotwordServiceFactory::GetInstance(); 258 259 MockHotwordService* hotword_service = static_cast<MockHotwordService*>( 260 hotword_service_factory->SetTestingFactoryAndUse( 261 profile(), BuildMockHotwordService)); 262 EXPECT_TRUE(hotword_service != NULL); 263 hotword_service->SetExtensionService(service()); 264 265 // Initialize the locale to "en". 266 SetApplicationLocale(profile(), "en"); 267 268 // The previous locale should not be set. No reason to uninstall. 269 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 270 271 // Do an initial installation. 272 hotword_service->InstallHotwordExtensionFromWebstore(); 273 base::MessageLoop::current()->RunUntilIdle(); 274 EXPECT_EQ("en", 275 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 276 277 // Verify the extension is installed but disabled. 278 EXPECT_EQ(1U, registry()->disabled_extensions().size()); 279 EXPECT_TRUE(registry()->disabled_extensions().Contains( 280 extension_misc::kHotwordExtensionId)); 281 282 // The previous locale should be set but should match the current 283 // locale. No reason to uninstall. 284 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 285 286 // Switch the locale to a valid but different one. 287 SetApplicationLocale(profile(), "fr_fr"); 288 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile())); 289 290 // Different but valid locale so expect uninstall. 291 EXPECT_TRUE(hotword_service->MaybeReinstallHotwordExtension()); 292 EXPECT_EQ(1, hotword_service->uninstall_count()); 293 EXPECT_EQ("fr_fr", 294 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 295 296 // Verify the extension is installed. It's still disabled. 297 EXPECT_TRUE(registry()->disabled_extensions().Contains( 298 extension_misc::kHotwordExtensionId)); 299 300 // Switch the locale to an invalid one. 301 SetApplicationLocale(profile(), "invalid"); 302 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile())); 303 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 304 EXPECT_EQ("fr_fr", 305 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 306 307 // If the locale is set back to the last valid one, then an uninstall-install 308 // shouldn't be needed. 309 SetApplicationLocale(profile(), "fr_fr"); 310 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile())); 311 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 312 EXPECT_EQ(1, hotword_service->uninstall_count()); // no change 313 } 314