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.get(), 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 scoped_ptr<TestingProfile> profile = profile_builder.Build(); 96 97 HotwordServiceFactory* hotword_service_factory = 98 HotwordServiceFactory::GetInstance(); 99 100 // Check that the service exists so that a NULL service be ruled out in 101 // following tests. 102 HotwordService* hotword_service = 103 hotword_service_factory->GetForProfile(profile.get()); 104 EXPECT_TRUE(hotword_service != NULL); 105 106 // When the field trial is empty or Disabled, it should not be allowed. 107 std::string group = base::FieldTrialList::FindFullName( 108 hotword_internal::kHotwordFieldTrialName); 109 EXPECT_TRUE(group.empty()); 110 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 111 112 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 113 hotword_internal::kHotwordFieldTrialName, 114 hotword_internal::kHotwordFieldTrialDisabledGroupName)); 115 group = base::FieldTrialList::FindFullName( 116 hotword_internal::kHotwordFieldTrialName); 117 EXPECT_TRUE(group ==hotword_internal::kHotwordFieldTrialDisabledGroupName); 118 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 119 120 // Set a valid locale with invalid field trial to be sure it is 121 // still false. 122 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en"); 123 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 124 125 // Test that incognito returns false as well. 126 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed( 127 profile->GetOffTheRecordProfile())); 128 } 129 130 TEST_F(HotwordServiceTest, IsHotwordAllowedLocale) { 131 TestingProfile::Builder profile_builder; 132 scoped_ptr<TestingProfile> profile = profile_builder.Build(); 133 134 HotwordServiceFactory* hotword_service_factory = 135 HotwordServiceFactory::GetInstance(); 136 137 // Check that the service exists so that a NULL service be ruled out in 138 // following tests. 139 HotwordService* hotword_service = 140 hotword_service_factory->GetForProfile(profile.get()); 141 EXPECT_TRUE(hotword_service != NULL); 142 143 // Set the field trial to a valid one. 144 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 145 hotword_internal::kHotwordFieldTrialName, "Good")); 146 147 // Set the language to an invalid one. 148 SetApplicationLocale(static_cast<Profile*>(profile.get()), "non-valid"); 149 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 150 151 // Now with valid locales it should be fine. 152 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en"); 153 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 154 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en-US"); 155 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 156 SetApplicationLocale(static_cast<Profile*>(profile.get()), "en_us"); 157 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 158 SetApplicationLocale(static_cast<Profile*>(profile.get()), "de_DE"); 159 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 160 SetApplicationLocale(static_cast<Profile*>(profile.get()), "fr_fr"); 161 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get())); 162 163 // Test that incognito even with a valid locale and valid field trial 164 // still returns false. 165 Profile* otr_profile = profile->GetOffTheRecordProfile(); 166 SetApplicationLocale(otr_profile, "en"); 167 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(otr_profile)); 168 } 169 170 TEST_F(HotwordServiceTest, AudioLoggingPrefSetCorrectly) { 171 TestingProfile::Builder profile_builder; 172 scoped_ptr<TestingProfile> profile = profile_builder.Build(); 173 174 HotwordServiceFactory* hotword_service_factory = 175 HotwordServiceFactory::GetInstance(); 176 HotwordService* hotword_service = 177 hotword_service_factory->GetForProfile(profile.get()); 178 EXPECT_TRUE(hotword_service != NULL); 179 180 // If it's a fresh profile, although the default value is true, 181 // it should return false if the preference has never been set. 182 EXPECT_FALSE(hotword_service->IsOptedIntoAudioLogging()); 183 } 184 185 TEST_F(HotwordServiceTest, ShouldReinstallExtension) { 186 // Set the field trial to a valid one. 187 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 188 hotword_internal::kHotwordFieldTrialName, "Install")); 189 190 InitializeEmptyExtensionService(); 191 192 HotwordServiceFactory* hotword_service_factory = 193 HotwordServiceFactory::GetInstance(); 194 195 MockHotwordService* hotword_service = static_cast<MockHotwordService*>( 196 hotword_service_factory->SetTestingFactoryAndUse( 197 profile(), BuildMockHotwordService)); 198 EXPECT_TRUE(hotword_service != NULL); 199 200 // If no locale has been set, no reason to uninstall. 201 EXPECT_FALSE(hotword_service->ShouldReinstallHotwordExtension()); 202 203 SetApplicationLocale(profile(), "en"); 204 hotword_service->SetPreviousLanguagePref(); 205 206 // Now a locale is set, but it hasn't changed. 207 EXPECT_FALSE(hotword_service->ShouldReinstallHotwordExtension()); 208 209 SetApplicationLocale(profile(), "fr_fr"); 210 211 // Now it's a different locale so it should uninstall. 212 EXPECT_TRUE(hotword_service->ShouldReinstallHotwordExtension()); 213 } 214 215 TEST_F(HotwordServiceTest, PreviousLanguageSetOnInstall) { 216 // Set the field trial to a valid one. 217 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 218 hotword_internal::kHotwordFieldTrialName, "Install")); 219 220 InitializeEmptyExtensionService(); 221 service_->Init(); 222 223 HotwordServiceFactory* hotword_service_factory = 224 HotwordServiceFactory::GetInstance(); 225 226 MockHotwordService* hotword_service = static_cast<MockHotwordService*>( 227 hotword_service_factory->SetTestingFactoryAndUse( 228 profile(), BuildMockHotwordService)); 229 EXPECT_TRUE(hotword_service != NULL); 230 hotword_service->SetExtensionService(service()); 231 232 // If no locale has been set, no reason to uninstall. 233 EXPECT_FALSE(hotword_service->ShouldReinstallHotwordExtension()); 234 235 SetApplicationLocale(profile(), "test_locale"); 236 237 hotword_service->InstallHotwordExtensionFromWebstore(); 238 base::MessageLoop::current()->RunUntilIdle(); 239 240 EXPECT_EQ("test_locale", 241 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 242 } 243 244 TEST_F(HotwordServiceTest, UninstallReinstallTriggeredCorrectly) { 245 // Set the field trial to a valid one. 246 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 247 hotword_internal::kHotwordFieldTrialName, "Install")); 248 249 InitializeEmptyExtensionService(); 250 service_->Init(); 251 252 HotwordServiceFactory* hotword_service_factory = 253 HotwordServiceFactory::GetInstance(); 254 255 MockHotwordService* hotword_service = static_cast<MockHotwordService*>( 256 hotword_service_factory->SetTestingFactoryAndUse( 257 profile(), BuildMockHotwordService)); 258 EXPECT_TRUE(hotword_service != NULL); 259 hotword_service->SetExtensionService(service()); 260 261 // Initialize the locale to "en". 262 SetApplicationLocale(profile(), "en"); 263 264 // The previous locale should not be set. No reason to uninstall. 265 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 266 267 // Do an initial installation. 268 hotword_service->InstallHotwordExtensionFromWebstore(); 269 base::MessageLoop::current()->RunUntilIdle(); 270 EXPECT_EQ("en", 271 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 272 273 // Verify the extension is installed but disabled. 274 EXPECT_EQ(1U, registry()->disabled_extensions().size()); 275 EXPECT_TRUE(registry()->disabled_extensions().Contains( 276 extension_misc::kHotwordExtensionId)); 277 278 // The previous locale should be set but should match the current 279 // locale. No reason to uninstall. 280 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 281 282 // Switch the locale to a valid but different one. 283 SetApplicationLocale(profile(), "fr_fr"); 284 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile())); 285 286 // Different but valid locale so expect uninstall. 287 EXPECT_TRUE(hotword_service->MaybeReinstallHotwordExtension()); 288 EXPECT_EQ(1, hotword_service->uninstall_count()); 289 EXPECT_EQ("fr_fr", 290 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 291 292 // Verify the extension is installed. It's still disabled. 293 EXPECT_TRUE(registry()->disabled_extensions().Contains( 294 extension_misc::kHotwordExtensionId)); 295 296 // Switch the locale to an invalid one. 297 SetApplicationLocale(profile(), "invalid"); 298 EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile())); 299 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 300 EXPECT_EQ("fr_fr", 301 profile()->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); 302 303 // If the locale is set back to the last valid one, then an uninstall-install 304 // shouldn't be needed. 305 SetApplicationLocale(profile(), "fr_fr"); 306 EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile())); 307 EXPECT_FALSE(hotword_service->MaybeReinstallHotwordExtension()); 308 EXPECT_EQ(1, hotword_service->uninstall_count()); // no change 309 } 310