1 // Copyright (c) 2011 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 "chrome/browser/sync/glue/extension_util.h" 6 7 #include "base/file_path.h" 8 #include "base/values.h" 9 #include "chrome/browser/extensions/mock_extension_service.h" 10 #include "chrome/browser/sync/protocol/extension_specifics.pb.h" 11 #include "chrome/common/extensions/extension.h" 12 #include "chrome/common/extensions/extension_constants.h" 13 #include "testing/gmock/include/gmock/gmock.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace browser_sync { 17 18 namespace { 19 20 using ::testing::_; 21 using ::testing::Return; 22 using ::testing::StrictMock; 23 24 #if defined(OS_WIN) 25 const FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("c:\\foo"); 26 #elif defined(OS_POSIX) 27 const FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("/foo"); 28 #endif 29 30 const char kValidId[] = "abcdefghijklmnopabcdefghijklmnop"; 31 const char kValidVersion[] = "0.0.0.0"; 32 const char kVersion1[] = "1.0.0.1"; 33 const char kVersion2[] = "1.0.1.0"; 34 const char kVersion3[] = "1.1.0.0"; 35 const char kValidUpdateUrl1[] = 36 "http://clients2.google.com/service/update2/crx"; 37 const char kValidUpdateUrl2[] = 38 "https://clients2.google.com/service/update2/crx"; 39 const char kName[] = "MyExtension"; 40 const char kName2[] = "MyExtension2"; 41 42 class ExtensionUtilTest : public testing::Test { 43 }; 44 45 scoped_refptr<Extension> MakeExtension( 46 bool is_theme, const GURL& update_url, 47 const GURL& launch_url, 48 bool converted_from_user_script, 49 Extension::Location location, int num_plugins, 50 const FilePath& extension_path) { 51 DictionaryValue source; 52 source.SetString(extension_manifest_keys::kName, 53 "PossiblySyncableExtension"); 54 source.SetString(extension_manifest_keys::kVersion, "0.0.0.0"); 55 if (is_theme) { 56 source.Set(extension_manifest_keys::kTheme, new DictionaryValue()); 57 } 58 if (!update_url.is_empty()) { 59 source.SetString(extension_manifest_keys::kUpdateURL, 60 update_url.spec()); 61 } 62 if (!launch_url.is_empty()) { 63 source.SetString(extension_manifest_keys::kLaunchWebURL, 64 launch_url.spec()); 65 } 66 if (!is_theme) { 67 source.SetBoolean(extension_manifest_keys::kConvertedFromUserScript, 68 converted_from_user_script); 69 ListValue* plugins = new ListValue(); 70 for (int i = 0; i < num_plugins; ++i) { 71 DictionaryValue* plugin = new DictionaryValue(); 72 plugin->SetString(extension_manifest_keys::kPluginsPath, ""); 73 plugins->Set(i, plugin); 74 } 75 source.Set(extension_manifest_keys::kPlugins, plugins); 76 } 77 78 std::string error; 79 scoped_refptr<Extension> extension = Extension::Create( 80 extension_path, location, source, Extension::STRICT_ERROR_CHECKS, &error); 81 EXPECT_TRUE(extension); 82 EXPECT_EQ("", error); 83 return extension; 84 } 85 86 TEST_F(ExtensionUtilTest, IsExtensionValid) { 87 { 88 FilePath file_path(kExtensionFilePath); 89 scoped_refptr<Extension> extension( 90 MakeExtension(false, GURL(), GURL(), false, 91 Extension::INTERNAL, 0, file_path)); 92 EXPECT_TRUE(IsExtensionValid(*extension)); 93 } 94 { 95 FilePath file_path(kExtensionFilePath); 96 scoped_refptr<Extension> extension( 97 MakeExtension(false, GURL(kValidUpdateUrl1), GURL(), 98 true, Extension::INTERNAL, 0, file_path)); 99 EXPECT_TRUE(IsExtensionValid(*extension)); 100 } 101 { 102 FilePath file_path(kExtensionFilePath); 103 scoped_refptr<Extension> extension( 104 MakeExtension(false, GURL(), GURL(), true, 105 Extension::INTERNAL, 0, file_path)); 106 EXPECT_TRUE(IsExtensionValid(*extension)); 107 } 108 { 109 FilePath file_path(kExtensionFilePath); 110 scoped_refptr<Extension> extension( 111 MakeExtension(true, GURL(), GURL(), false, 112 Extension::INTERNAL, 0, file_path)); 113 EXPECT_TRUE(IsExtensionValid(*extension)); 114 } 115 { 116 FilePath file_path(kExtensionFilePath); 117 scoped_refptr<Extension> extension( 118 MakeExtension(false, GURL(), 119 GURL("http://www.google.com"), false, 120 Extension::INTERNAL, 0, file_path)); 121 EXPECT_TRUE(IsExtensionValid(*extension)); 122 } 123 { 124 FilePath file_path(kExtensionFilePath); 125 scoped_refptr<Extension> extension( 126 MakeExtension(false, GURL(), GURL(), false, 127 Extension::EXTERNAL_PREF, 0, file_path)); 128 EXPECT_FALSE(IsExtensionValid(*extension)); 129 } 130 { 131 FilePath file_path(kExtensionFilePath); 132 scoped_refptr<Extension> extension( 133 MakeExtension( 134 false, GURL("http://third-party.update_url.com"), GURL(), true, 135 Extension::INTERNAL, 0, file_path)); 136 EXPECT_FALSE(IsExtensionValid(*extension)); 137 } 138 // These last 2 tests don't make sense on Chrome OS, where extension plugins 139 // are not allowed. 140 #if !defined(OS_CHROMEOS) 141 { 142 FilePath file_path(kExtensionFilePath); 143 scoped_refptr<Extension> extension( 144 MakeExtension(false, GURL(), GURL(), true, 145 Extension::INTERNAL, 1, file_path)); 146 EXPECT_FALSE(extension && IsExtensionValid(*extension)); 147 } 148 { 149 FilePath file_path(kExtensionFilePath); 150 scoped_refptr<Extension> extension( 151 MakeExtension(false, GURL(), GURL(), true, 152 Extension::INTERNAL, 2, file_path)); 153 EXPECT_FALSE(extension && IsExtensionValid(*extension)); 154 } 155 #endif 156 } 157 158 TEST_F(ExtensionUtilTest, IsExtensionSpecificsUnset) { 159 { 160 sync_pb::ExtensionSpecifics specifics; 161 EXPECT_TRUE(IsExtensionSpecificsUnset(specifics)); 162 } 163 164 { 165 sync_pb::ExtensionSpecifics specifics; 166 specifics.set_id("a"); 167 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 168 } 169 170 { 171 sync_pb::ExtensionSpecifics specifics; 172 specifics.set_version("a"); 173 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 174 } 175 176 { 177 sync_pb::ExtensionSpecifics specifics; 178 specifics.set_update_url("a"); 179 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 180 } 181 182 { 183 sync_pb::ExtensionSpecifics specifics; 184 specifics.set_enabled(true); 185 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 186 } 187 188 { 189 sync_pb::ExtensionSpecifics specifics; 190 specifics.set_incognito_enabled(true); 191 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 192 } 193 194 { 195 sync_pb::ExtensionSpecifics specifics; 196 specifics.set_name("a"); 197 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 198 } 199 } 200 201 TEST_F(ExtensionUtilTest, IsExtensionSpecificsValid) { 202 sync_pb::ExtensionSpecifics specifics; 203 EXPECT_FALSE(IsExtensionSpecificsValid(specifics)); 204 specifics.set_id(kValidId); 205 EXPECT_FALSE(IsExtensionSpecificsValid(specifics)); 206 specifics.set_version(kValidVersion); 207 EXPECT_TRUE(IsExtensionSpecificsValid(specifics)); 208 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 209 specifics.set_update_url(kValidUpdateUrl1); 210 EXPECT_TRUE(IsExtensionSpecificsValid(specifics)); 211 EXPECT_FALSE(IsExtensionSpecificsUnset(specifics)); 212 213 { 214 sync_pb::ExtensionSpecifics specifics_copy(specifics); 215 specifics_copy.set_id("invalid"); 216 EXPECT_FALSE(IsExtensionSpecificsValid(specifics_copy)); 217 } 218 219 { 220 sync_pb::ExtensionSpecifics specifics_copy(specifics); 221 specifics_copy.set_version("invalid"); 222 EXPECT_FALSE(IsExtensionSpecificsValid(specifics_copy)); 223 } 224 225 { 226 sync_pb::ExtensionSpecifics specifics_copy(specifics); 227 specifics_copy.set_update_url("http:invalid.com:invalid"); 228 EXPECT_FALSE(IsExtensionSpecificsValid(specifics_copy)); 229 } 230 } 231 232 TEST_F(ExtensionUtilTest, AreExtensionSpecificsEqual) { 233 sync_pb::ExtensionSpecifics a, b; 234 EXPECT_TRUE(AreExtensionSpecificsEqual(a, b)); 235 236 a.set_id("a"); 237 EXPECT_FALSE(AreExtensionSpecificsEqual(a, b)); 238 b.set_id("a"); 239 EXPECT_TRUE(AreExtensionSpecificsEqual(a, b)); 240 241 a.set_version("1.5"); 242 EXPECT_FALSE(AreExtensionSpecificsEqual(a, b)); 243 b.set_version("1.5"); 244 EXPECT_TRUE(AreExtensionSpecificsEqual(a, b)); 245 246 a.set_update_url("http://www.foo.com"); 247 EXPECT_FALSE(AreExtensionSpecificsEqual(a, b)); 248 b.set_update_url("http://www.foo.com"); 249 EXPECT_TRUE(AreExtensionSpecificsEqual(a, b)); 250 251 a.set_enabled(true); 252 EXPECT_FALSE(AreExtensionSpecificsEqual(a, b)); 253 b.set_enabled(true); 254 EXPECT_TRUE(AreExtensionSpecificsEqual(a, b)); 255 256 a.set_incognito_enabled(true); 257 EXPECT_FALSE(AreExtensionSpecificsEqual(a, b)); 258 b.set_incognito_enabled(true); 259 EXPECT_TRUE(AreExtensionSpecificsEqual(a, b)); 260 261 a.set_name("name"); 262 EXPECT_FALSE(AreExtensionSpecificsEqual(a, b)); 263 b.set_name("name"); 264 EXPECT_TRUE(AreExtensionSpecificsEqual(a, b)); 265 } 266 267 TEST_F(ExtensionUtilTest, CopyUserProperties) { 268 sync_pb::ExtensionSpecifics dest_specifics; 269 dest_specifics.set_version(kVersion2); 270 dest_specifics.set_update_url(kValidUpdateUrl1); 271 dest_specifics.set_enabled(true); 272 dest_specifics.set_incognito_enabled(false); 273 dest_specifics.set_name(kName); 274 275 sync_pb::ExtensionSpecifics specifics; 276 specifics.set_id(kValidId); 277 specifics.set_version(kVersion3); 278 specifics.set_update_url(kValidUpdateUrl2); 279 specifics.set_enabled(false); 280 specifics.set_incognito_enabled(true); 281 specifics.set_name(kName2); 282 283 CopyUserProperties(specifics, &dest_specifics); 284 EXPECT_EQ("", dest_specifics.id()); 285 EXPECT_EQ(kVersion2, dest_specifics.version()); 286 EXPECT_EQ(kValidUpdateUrl1, dest_specifics.update_url()); 287 EXPECT_FALSE(dest_specifics.enabled()); 288 EXPECT_TRUE(dest_specifics.incognito_enabled()); 289 EXPECT_EQ(kName, dest_specifics.name()); 290 } 291 292 TEST_F(ExtensionUtilTest, CopyNonUserProperties) { 293 sync_pb::ExtensionSpecifics dest_specifics; 294 dest_specifics.set_id(kValidId); 295 dest_specifics.set_version(kVersion2); 296 dest_specifics.set_update_url(kValidUpdateUrl1); 297 dest_specifics.set_enabled(true); 298 dest_specifics.set_incognito_enabled(false); 299 dest_specifics.set_name(kName); 300 301 sync_pb::ExtensionSpecifics specifics; 302 specifics.set_id(""); 303 specifics.set_version(kVersion3); 304 specifics.set_update_url(kValidUpdateUrl2); 305 specifics.set_enabled(false); 306 specifics.set_incognito_enabled(true); 307 specifics.set_name(kName2); 308 309 CopyNonUserProperties(specifics, &dest_specifics); 310 EXPECT_EQ("", dest_specifics.id()); 311 EXPECT_EQ(kVersion3, dest_specifics.version()); 312 EXPECT_EQ(kValidUpdateUrl2, dest_specifics.update_url()); 313 EXPECT_TRUE(dest_specifics.enabled()); 314 EXPECT_FALSE(dest_specifics.incognito_enabled()); 315 EXPECT_EQ(kName2, dest_specifics.name()); 316 } 317 318 TEST_F(ExtensionUtilTest, AreExtensionSpecificsUserPropertiesEqual) { 319 sync_pb::ExtensionSpecifics a, b; 320 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 321 322 a.set_id("a"); 323 b.set_id("b"); 324 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 325 326 a.set_version("1.5"); 327 b.set_version("1.6"); 328 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 329 330 a.set_name("name"); 331 b.set_name("name2"); 332 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 333 334 a.set_update_url("http://www.foo.com"); 335 b.set_update_url("http://www.foo2.com"); 336 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 337 338 a.set_enabled(true); 339 EXPECT_FALSE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 340 b.set_enabled(true); 341 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 342 343 a.set_incognito_enabled(true); 344 EXPECT_FALSE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 345 b.set_incognito_enabled(true); 346 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b)); 347 } 348 349 TEST_F(ExtensionUtilTest, AreExtensionSpecificsNonUserPropertiesEqual) { 350 sync_pb::ExtensionSpecifics a, b; 351 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 352 353 a.set_enabled(true); 354 b.set_enabled(false); 355 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 356 357 a.set_incognito_enabled(true); 358 b.set_incognito_enabled(false); 359 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 360 361 a.set_id("a"); 362 EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 363 b.set_id("a"); 364 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 365 366 a.set_version("1.5"); 367 EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 368 b.set_version("1.5"); 369 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 370 371 a.set_update_url("http://www.foo.com"); 372 EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 373 b.set_update_url("http://www.foo.com"); 374 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 375 376 a.set_name("name"); 377 EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 378 b.set_name("name"); 379 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b)); 380 } 381 382 scoped_refptr<Extension> MakeSyncableExtension( 383 const std::string& version_string, 384 const std::string& update_url_spec, 385 const std::string& name, 386 const FilePath& extension_path) { 387 DictionaryValue source; 388 source.SetString(extension_manifest_keys::kVersion, version_string); 389 source.SetString(extension_manifest_keys::kUpdateURL, update_url_spec); 390 source.SetString(extension_manifest_keys::kName, name); 391 std::string error; 392 scoped_refptr<Extension> extension = Extension::Create( 393 extension_path, Extension::INTERNAL, source, 394 Extension::STRICT_ERROR_CHECKS, &error); 395 EXPECT_TRUE(extension); 396 EXPECT_EQ("", error); 397 return extension; 398 } 399 400 TEST_F(ExtensionUtilTest, GetExtensionSpecifics) { 401 FilePath file_path(kExtensionFilePath); 402 StrictMock<MockExtensionService> mock_extension_service; 403 EXPECT_CALL(mock_extension_service, IsExtensionEnabled(_)) 404 .WillOnce(Return(true)); 405 EXPECT_CALL(mock_extension_service, IsIncognitoEnabled(_)) 406 .WillOnce(Return(false)); 407 408 scoped_refptr<Extension> extension( 409 MakeSyncableExtension( 410 kValidVersion, kValidUpdateUrl1, kName, file_path)); 411 sync_pb::ExtensionSpecifics specifics; 412 GetExtensionSpecifics(*extension, mock_extension_service, &specifics); 413 EXPECT_EQ(extension->id(), specifics.id()); 414 EXPECT_EQ(extension->VersionString(), kValidVersion); 415 EXPECT_EQ(extension->update_url().spec(), kValidUpdateUrl1); 416 EXPECT_TRUE(specifics.enabled()); 417 EXPECT_FALSE(specifics.incognito_enabled()); 418 EXPECT_EQ(kName, specifics.name()); 419 } 420 421 // TODO(akalin): Make ExtensionService/ExtensionUpdater testable 422 // enough to be able to write a unittest for SetExtensionProperties(). 423 424 TEST_F(ExtensionUtilTest, MergeExtensionSpecificsWithUserProperties) { 425 sync_pb::ExtensionSpecifics merged_specifics; 426 merged_specifics.set_id(kValidId); 427 merged_specifics.set_update_url(kValidUpdateUrl1); 428 merged_specifics.set_enabled(true); 429 merged_specifics.set_incognito_enabled(false); 430 merged_specifics.set_version(kVersion2); 431 432 sync_pb::ExtensionSpecifics specifics; 433 specifics.set_id(kValidId); 434 specifics.set_update_url(kValidUpdateUrl2); 435 merged_specifics.set_enabled(false); 436 merged_specifics.set_incognito_enabled(true); 437 438 specifics.set_version(kVersion1); 439 { 440 sync_pb::ExtensionSpecifics result = merged_specifics; 441 MergeExtensionSpecifics(specifics, false, &result); 442 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual( 443 result, merged_specifics)); 444 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual( 445 result, merged_specifics)); 446 } 447 { 448 sync_pb::ExtensionSpecifics result = merged_specifics; 449 MergeExtensionSpecifics(specifics, true, &result); 450 EXPECT_TRUE(AreExtensionSpecificsEqual(result, merged_specifics)); 451 } 452 453 specifics.set_version(kVersion2); 454 { 455 sync_pb::ExtensionSpecifics result = merged_specifics; 456 MergeExtensionSpecifics(specifics, false, &result); 457 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual( 458 result, merged_specifics)); 459 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual( 460 result, specifics)); 461 } 462 { 463 sync_pb::ExtensionSpecifics result = merged_specifics; 464 MergeExtensionSpecifics(specifics, true, &result); 465 EXPECT_TRUE(AreExtensionSpecificsEqual(result, specifics)); 466 } 467 468 specifics.set_version(kVersion3); 469 { 470 sync_pb::ExtensionSpecifics result = merged_specifics; 471 MergeExtensionSpecifics(specifics, false, &result); 472 EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual( 473 result, merged_specifics)); 474 EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual( 475 result, specifics)); 476 } 477 { 478 sync_pb::ExtensionSpecifics result = merged_specifics; 479 MergeExtensionSpecifics(specifics, true, &result); 480 EXPECT_TRUE(AreExtensionSpecificsEqual(result, specifics)); 481 } 482 } 483 484 } // namespace 485 486 } // namespace browser_sync 487