| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/install_verifier.h" | 5 #include "chrome/browser/extensions/install_verifier.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 // the "MAX" item below should always be the last element. | 121 // the "MAX" item below should always be the last element. |
| 122 | 122 |
| 123 INIT_RESULT_MAX | 123 INIT_RESULT_MAX |
| 124 }; | 124 }; |
| 125 | 125 |
| 126 void LogInitResultHistogram(InitResult result) { | 126 void LogInitResultHistogram(InitResult result) { |
| 127 UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.InitResult", | 127 UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.InitResult", |
| 128 result, INIT_RESULT_MAX); | 128 result, INIT_RESULT_MAX); |
| 129 } | 129 } |
| 130 | 130 |
| 131 bool FromStore(const Extension& extension) { | |
| 132 if (extension.from_webstore() || ManifestURL::UpdatesFromGallery(&extension)) | |
| 133 return true; | |
| 134 | |
| 135 // If an extension has no update url, our autoupdate code will ask the | |
| 136 // webstore about it (to aid in migrating to the webstore from self-hosting | |
| 137 // or sideloading based installs). So we want to do verification checks on | |
| 138 // such extensions too so that we don't accidentally disable old installs of | |
| 139 // extensions that did migrate to the webstore. | |
| 140 return (ManifestURL::GetUpdateURL(&extension).is_empty() && | |
| 141 Manifest::IsAutoUpdateableLocation(extension.location())); | |
| 142 } | |
| 143 | |
| 144 bool CanUseExtensionApis(const Extension& extension) { | 131 bool CanUseExtensionApis(const Extension& extension) { |
| 145 return extension.is_extension() || extension.is_legacy_packaged_app(); | 132 return extension.is_extension() || extension.is_legacy_packaged_app(); |
| 146 } | 133 } |
| 147 | 134 |
| 148 enum VerifyAllSuccess { | 135 enum VerifyAllSuccess { |
| 149 VERIFY_ALL_BOOTSTRAP_SUCCESS = 0, | 136 VERIFY_ALL_BOOTSTRAP_SUCCESS = 0, |
| 150 VERIFY_ALL_BOOTSTRAP_FAILURE, | 137 VERIFY_ALL_BOOTSTRAP_FAILURE, |
| 151 VERIFY_ALL_NON_BOOTSTRAP_SUCCESS, | 138 VERIFY_ALL_NON_BOOTSTRAP_SUCCESS, |
| 152 VERIFY_ALL_NON_BOOTSTRAP_FAILURE, | 139 VERIFY_ALL_NON_BOOTSTRAP_FAILURE, |
| 153 | 140 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 : prefs_(prefs), | 176 : prefs_(prefs), |
| 190 context_(context), | 177 context_(context), |
| 191 bootstrap_check_complete_(false), | 178 bootstrap_check_complete_(false), |
| 192 weak_factory_(this) { | 179 weak_factory_(this) { |
| 193 } | 180 } |
| 194 | 181 |
| 195 InstallVerifier::~InstallVerifier() {} | 182 InstallVerifier::~InstallVerifier() {} |
| 196 | 183 |
| 197 // static | 184 // static |
| 198 bool InstallVerifier::NeedsVerification(const Extension& extension) { | 185 bool InstallVerifier::NeedsVerification(const Extension& extension) { |
| 199 return FromStore(extension) && CanUseExtensionApis(extension); | 186 return IsFromStore(extension) && CanUseExtensionApis(extension); |
| 187 } |
| 188 |
| 189 |
| 190 |
| 191 // static |
| 192 bool InstallVerifier::IsFromStore(const Extension& extension) { |
| 193 if (extension.from_webstore() || ManifestURL::UpdatesFromGallery(&extension)) |
| 194 return true; |
| 195 |
| 196 // If an extension has no update url, our autoupdate code will ask the |
| 197 // webstore about it (to aid in migrating to the webstore from self-hosting |
| 198 // or sideloading based installs). So we want to do verification checks on |
| 199 // such extensions too so that we don't accidentally disable old installs of |
| 200 // extensions that did migrate to the webstore. |
| 201 return (ManifestURL::GetUpdateURL(&extension).is_empty() && |
| 202 Manifest::IsAutoUpdateableLocation(extension.location())); |
| 200 } | 203 } |
| 201 | 204 |
| 202 void InstallVerifier::Init() { | 205 void InstallVerifier::Init() { |
| 203 UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.ExperimentStatus", | 206 UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.ExperimentStatus", |
| 204 GetExperimentStatus(), VERIFY_STATUS_MAX); | 207 GetExperimentStatus(), VERIFY_STATUS_MAX); |
| 205 UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.ActualStatus", | 208 UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.ActualStatus", |
| 206 GetStatus(), VERIFY_STATUS_MAX); | 209 GetStatus(), VERIFY_STATUS_MAX); |
| 207 | 210 |
| 208 const base::DictionaryValue* pref = prefs_->GetInstallSignature(); | 211 const base::DictionaryValue* pref = prefs_->GetInstallSignature(); |
| 209 if (pref) { | 212 if (pref) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 235 AddMany(GetExtensionsToVerify(), ADD_ALL); | 238 AddMany(GetExtensionsToVerify(), ADD_ALL); |
| 236 } | 239 } |
| 237 | 240 |
| 238 base::Time InstallVerifier::SignatureTimestamp() { | 241 base::Time InstallVerifier::SignatureTimestamp() { |
| 239 if (signature_.get()) | 242 if (signature_.get()) |
| 240 return signature_->timestamp; | 243 return signature_->timestamp; |
| 241 else | 244 else |
| 242 return base::Time(); | 245 return base::Time(); |
| 243 } | 246 } |
| 244 | 247 |
| 245 bool InstallVerifier::IsKnownId(const std::string& id) { | 248 bool InstallVerifier::IsKnownId(const std::string& id) const { |
| 246 return signature_.get() && (ContainsKey(signature_->ids, id) || | 249 return signature_.get() && (ContainsKey(signature_->ids, id) || |
| 247 ContainsKey(signature_->invalid_ids, id)); | 250 ContainsKey(signature_->invalid_ids, id)); |
| 248 } | 251 } |
| 249 | 252 |
| 253 bool InstallVerifier::IsInvalid(const std::string& id) const { |
| 254 return ((signature_.get() && ContainsKey(signature_->invalid_ids, id))); |
| 255 } |
| 256 |
| 250 void InstallVerifier::VerifyExtension(const std::string& extension_id) { | 257 void InstallVerifier::VerifyExtension(const std::string& extension_id) { |
| 251 ExtensionIdSet ids; | 258 ExtensionIdSet ids; |
| 252 ids.insert(extension_id); | 259 ids.insert(extension_id); |
| 253 AddMany(ids, ADD_SINGLE); | 260 AddMany(ids, ADD_SINGLE); |
| 254 } | 261 } |
| 255 | 262 |
| 256 void InstallVerifier::AddMany(const ExtensionIdSet& ids, OperationType type) { | 263 void InstallVerifier::AddMany(const ExtensionIdSet& ids, OperationType type) { |
| 257 if (!ShouldFetchSignature()) { | 264 if (!ShouldFetchSignature()) { |
| 258 OnVerificationComplete(true, type); // considered successful. | 265 OnVerificationComplete(true, type); // considered successful. |
| 259 return; | 266 return; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 | 314 |
| 308 InstallVerifier::PendingOperation* operation = | 315 InstallVerifier::PendingOperation* operation = |
| 309 new InstallVerifier::PendingOperation(InstallVerifier::REMOVE); | 316 new InstallVerifier::PendingOperation(InstallVerifier::REMOVE); |
| 310 operation->ids = ids; | 317 operation->ids = ids; |
| 311 | 318 |
| 312 operation_queue_.push(linked_ptr<PendingOperation>(operation)); | 319 operation_queue_.push(linked_ptr<PendingOperation>(operation)); |
| 313 if (operation_queue_.size() == 1) | 320 if (operation_queue_.size() == 1) |
| 314 BeginFetch(); | 321 BeginFetch(); |
| 315 } | 322 } |
| 316 | 323 |
| 324 bool InstallVerifier::AllowedByEnterprisePolicy(const std::string& id) const { |
| 325 PrefService* pref_service = prefs_->pref_service(); |
| 326 if (pref_service->IsManagedPreference(pref_names::kInstallAllowList)) { |
| 327 const base::ListValue* whitelist = |
| 328 pref_service->GetList(pref_names::kInstallAllowList); |
| 329 base::StringValue id_value(id); |
| 330 if (whitelist && whitelist->Find(id_value) != whitelist->end()) |
| 331 return true; |
| 332 } |
| 333 if (pref_service->IsManagedPreference(pref_names::kInstallForceList)) { |
| 334 const base::DictionaryValue* forcelist = |
| 335 pref_service->GetDictionary(pref_names::kInstallForceList); |
| 336 if (forcelist && forcelist->HasKey(id)) |
| 337 return true; |
| 338 } |
| 339 return false; |
| 340 } |
| 341 |
| 317 std::string InstallVerifier::GetDebugPolicyProviderName() const { | 342 std::string InstallVerifier::GetDebugPolicyProviderName() const { |
| 318 return std::string("InstallVerifier"); | 343 return std::string("InstallVerifier"); |
| 319 } | 344 } |
| 320 | 345 |
| 321 namespace { | 346 namespace { |
| 322 | 347 |
| 323 enum MustRemainDisabledOutcome { | 348 enum MustRemainDisabledOutcome { |
| 324 VERIFIED = 0, | 349 VERIFIED = 0, |
| 325 NOT_EXTENSION, | 350 NOT_EXTENSION, |
| 326 UNPACKED, | 351 UNPACKED, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 if (AllowedByEnterprisePolicy(extension->id())) { | 390 if (AllowedByEnterprisePolicy(extension->id())) { |
| 366 MustRemainDisabledHistogram(ENTERPRISE_POLICY_ALLOWED); | 391 MustRemainDisabledHistogram(ENTERPRISE_POLICY_ALLOWED); |
| 367 return false; | 392 return false; |
| 368 } | 393 } |
| 369 | 394 |
| 370 bool verified = true; | 395 bool verified = true; |
| 371 MustRemainDisabledOutcome outcome = VERIFIED; | 396 MustRemainDisabledOutcome outcome = VERIFIED; |
| 372 if (ContainsKey(InstallSigner::GetForcedNotFromWebstore(), extension->id())) { | 397 if (ContainsKey(InstallSigner::GetForcedNotFromWebstore(), extension->id())) { |
| 373 verified = false; | 398 verified = false; |
| 374 outcome = FORCED_NOT_VERIFIED; | 399 outcome = FORCED_NOT_VERIFIED; |
| 375 } else if (!FromStore(*extension)) { | 400 } else if (!IsFromStore(*extension)) { |
| 376 verified = false; | 401 verified = false; |
| 377 outcome = NOT_FROM_STORE; | 402 outcome = NOT_FROM_STORE; |
| 378 } else if (signature_.get() == NULL && | 403 } else if (signature_.get() == NULL && |
| 379 (!bootstrap_check_complete_ || GetStatus() < ENFORCE_STRICT)) { | 404 (!bootstrap_check_complete_ || GetStatus() < ENFORCE_STRICT)) { |
| 380 // If we don't have a signature yet, we'll temporarily consider every | 405 // If we don't have a signature yet, we'll temporarily consider every |
| 381 // extension from the webstore verified to avoid false positives on existing | 406 // extension from the webstore verified to avoid false positives on existing |
| 382 // profiles hitting this code for the first time. The InstallVerifier | 407 // profiles hitting this code for the first time. The InstallVerifier |
| 383 // will bootstrap itself once the ExtensionsSystem is ready. | 408 // will bootstrap itself once the ExtensionsSystem is ready. |
| 384 outcome = NO_SIGNATURE; | 409 outcome = NO_SIGNATURE; |
| 385 } else if (!IsVerified(extension->id())) { | 410 } else if (!IsVerified(extension->id())) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 i != all_ids.end(); ++i) { | 528 i != all_ids.end(); ++i) { |
| 504 ExtensionIdSet::iterator found = leftovers.find(*i); | 529 ExtensionIdSet::iterator found = leftovers.find(*i); |
| 505 if (found != leftovers.end()) | 530 if (found != leftovers.end()) |
| 506 leftovers.erase(found); | 531 leftovers.erase(found); |
| 507 } | 532 } |
| 508 if (!leftovers.empty()) { | 533 if (!leftovers.empty()) { |
| 509 RemoveMany(leftovers); | 534 RemoveMany(leftovers); |
| 510 } | 535 } |
| 511 } | 536 } |
| 512 | 537 |
| 513 bool InstallVerifier::AllowedByEnterprisePolicy(const std::string& id) const { | |
| 514 PrefService* pref_service = prefs_->pref_service(); | |
| 515 if (pref_service->IsManagedPreference(pref_names::kInstallAllowList)) { | |
| 516 const base::ListValue* whitelist = | |
| 517 pref_service->GetList(pref_names::kInstallAllowList); | |
| 518 base::StringValue id_value(id); | |
| 519 if (whitelist && whitelist->Find(id_value) != whitelist->end()) | |
| 520 return true; | |
| 521 } | |
| 522 if (pref_service->IsManagedPreference(pref_names::kInstallForceList)) { | |
| 523 const base::DictionaryValue* forcelist = | |
| 524 pref_service->GetDictionary(pref_names::kInstallForceList); | |
| 525 if (forcelist && forcelist->HasKey(id)) | |
| 526 return true; | |
| 527 } | |
| 528 return false; | |
| 529 } | |
| 530 | |
| 531 bool InstallVerifier::IsVerified(const std::string& id) const { | 538 bool InstallVerifier::IsVerified(const std::string& id) const { |
| 532 return ((signature_.get() && ContainsKey(signature_->ids, id)) || | 539 return ((signature_.get() && ContainsKey(signature_->ids, id)) || |
| 533 ContainsKey(provisional_, id)); | 540 ContainsKey(provisional_, id)); |
| 534 } | 541 } |
| 535 | 542 |
| 536 void InstallVerifier::BeginFetch() { | 543 void InstallVerifier::BeginFetch() { |
| 537 DCHECK(ShouldFetchSignature()); | 544 DCHECK(ShouldFetchSignature()); |
| 538 | 545 |
| 539 // TODO(asargent) - It would be possible to coalesce all operations in the | 546 // TODO(asargent) - It would be possible to coalesce all operations in the |
| 540 // queue into one fetch - we'd probably just need to change the queue to | 547 // queue into one fetch - we'd probably just need to change the queue to |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 } | 642 } |
| 636 | 643 |
| 637 OnVerificationComplete(success, operation->type); | 644 OnVerificationComplete(success, operation->type); |
| 638 } | 645 } |
| 639 | 646 |
| 640 if (!operation_queue_.empty()) | 647 if (!operation_queue_.empty()) |
| 641 BeginFetch(); | 648 BeginFetch(); |
| 642 } | 649 } |
| 643 | 650 |
| 644 } // namespace extensions | 651 } // namespace extensions |
| OLD | NEW |