Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/chrome_content_verifier_delegate.h" | 5 #include "chrome/browser/extensions/chrome_content_verifier_delegate.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/base_switches.h" | 12 #include "base/base_switches.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/metrics/field_trial.h" | 15 #include "base/metrics/field_trial.h" |
| 16 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 17 #include "base/strings/string_piece.h" | 17 #include "base/strings/string_piece.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/syslog_logging.h" | 19 #include "base/syslog_logging.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 20 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "base/version.h" | 21 #include "base/version.h" |
| 22 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 23 #include "chrome/browser/extensions/extension_service.h" | 23 #include "chrome/browser/extensions/extension_service.h" |
| 24 #include "chrome/browser/extensions/policy_extension_reinstaller.h" | |
| 24 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
| 25 #include "chrome/common/extensions/extension_constants.h" | 26 #include "chrome/common/extensions/extension_constants.h" |
| 27 #include "content/public/browser/browser_thread.h" | |
| 26 #include "extensions/browser/extension_prefs.h" | 28 #include "extensions/browser/extension_prefs.h" |
| 27 #include "extensions/browser/extension_registry.h" | 29 #include "extensions/browser/extension_registry.h" |
| 28 #include "extensions/browser/extension_system.h" | 30 #include "extensions/browser/extension_system.h" |
| 29 #include "extensions/browser/management_policy.h" | 31 #include "extensions/browser/management_policy.h" |
| 30 #include "extensions/common/constants.h" | 32 #include "extensions/common/constants.h" |
| 31 #include "extensions/common/extension.h" | 33 #include "extensions/common/extension.h" |
| 32 #include "extensions/common/extension_urls.h" | 34 #include "extensions/common/extension_urls.h" |
| 33 #include "extensions/common/extensions_client.h" | 35 #include "extensions/common/extensions_client.h" |
| 34 #include "extensions/common/manifest.h" | 36 #include "extensions/common/manifest.h" |
| 35 #include "extensions/common/manifest_url_handlers.h" | 37 #include "extensions/common/manifest_url_handlers.h" |
| 36 #include "net/base/backoff_entry.h" | 38 #include "net/base/backoff_entry.h" |
| 37 #include "net/base/escape.h" | 39 #include "net/base/escape.h" |
| 38 | 40 |
| 39 #if defined(OS_CHROMEOS) | 41 #if defined(OS_CHROMEOS) |
| 40 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h" | 42 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h" |
| 41 #endif | 43 #endif |
| 42 | 44 |
| 43 namespace { | 45 namespace { |
| 44 | 46 |
| 45 const char kContentVerificationExperimentName[] = | 47 const char kContentVerificationExperimentName[] = |
| 46 "ExtensionContentVerification"; | 48 "ExtensionContentVerification"; |
| 47 | 49 |
| 48 const net::BackoffEntry::Policy kPolicyReinstallBackoffPolicy = { | |
| 49 // num_errors_to_ignore | |
| 50 1, | |
| 51 | |
| 52 // initial_delay_ms (note that we set 'always_use_initial_delay' to false | |
| 53 // below) | |
| 54 100, | |
| 55 | |
| 56 // multiply_factor | |
| 57 2, | |
| 58 | |
| 59 // jitter_factor | |
| 60 0.1, | |
| 61 | |
| 62 // maximum_backoff_ms (30 minutes) | |
| 63 1000 * 60 * 30, | |
| 64 | |
| 65 // entry_lifetime_ms (6 hours) | |
| 66 1000 * 60 * 60 * 6, | |
| 67 | |
| 68 // always_use_initial_delay | |
| 69 false, | |
| 70 }; | |
| 71 | |
| 72 base::Callback<void(base::TimeDelta delay)>* g_reinstall_action_for_test = | |
| 73 nullptr; | |
| 74 | 50 |
| 75 } // namespace | 51 } // namespace |
| 76 | 52 |
| 77 namespace extensions { | 53 namespace extensions { |
| 78 | 54 |
| 79 // static | 55 // static |
| 80 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::GetDefaultMode() { | 56 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::GetDefaultMode() { |
| 81 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 57 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 82 | 58 |
| 83 Mode experiment_value; | 59 Mode experiment_value; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 128 } | 104 } |
| 129 | 105 |
| 130 // We don't want to allow the command-line flags to eg disable enforcement | 106 // We don't want to allow the command-line flags to eg disable enforcement |
| 131 // if the experiment group says it should be on, or malware may just modify | 107 // if the experiment group says it should be on, or malware may just modify |
| 132 // the command line flags. So return the more restrictive of the 2 values. | 108 // the command line flags. So return the more restrictive of the 2 values. |
| 133 return std::max(experiment_value, cmdline_value); | 109 return std::max(experiment_value, cmdline_value); |
| 134 } | 110 } |
| 135 | 111 |
| 136 ChromeContentVerifierDelegate::ChromeContentVerifierDelegate( | 112 ChromeContentVerifierDelegate::ChromeContentVerifierDelegate( |
| 137 content::BrowserContext* context) | 113 content::BrowserContext* context) |
| 138 : context_(context), default_mode_(GetDefaultMode()) {} | 114 : context_(context), |
| 115 default_mode_(GetDefaultMode()), | |
| 116 policy_extension_reinstaller_( | |
| 117 base::MakeUnique<PolicyExtensionReinstaller>(context_)) {} | |
| 139 | 118 |
| 140 ChromeContentVerifierDelegate::~ChromeContentVerifierDelegate() { | 119 ChromeContentVerifierDelegate::~ChromeContentVerifierDelegate() { |
| 141 } | 120 } |
| 142 | 121 |
| 143 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::ShouldBeVerified( | 122 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::ShouldBeVerified( |
| 144 const Extension& extension) { | 123 const Extension& extension) { |
| 145 #if defined(OS_CHROMEOS) | 124 #if defined(OS_CHROMEOS) |
| 146 if (ExtensionAssetsManagerChromeOS::IsSharedInstall(&extension)) | 125 if (ExtensionAssetsManagerChromeOS::IsSharedInstall(&extension)) |
| 147 return ContentVerifierDelegate::ENFORCE_STRICT; | 126 return ContentVerifierDelegate::ENFORCE_STRICT; |
| 148 #endif | 127 #endif |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 if (system->management_policy()->MustRemainEnabled(extension, NULL)) { | 188 if (system->management_policy()->MustRemainEnabled(extension, NULL)) { |
| 210 PendingExtensionManager* pending_manager = | 189 PendingExtensionManager* pending_manager = |
| 211 service->pending_extension_manager(); | 190 service->pending_extension_manager(); |
| 212 if (pending_manager->IsPolicyReinstallForCorruptionExpected(extension_id)) | 191 if (pending_manager->IsPolicyReinstallForCorruptionExpected(extension_id)) |
| 213 return; | 192 return; |
| 214 SYSLOG(WARNING) << "Corruption detected in policy extension " | 193 SYSLOG(WARNING) << "Corruption detected in policy extension " |
| 215 << extension_id << " installed at: " | 194 << extension_id << " installed at: " |
| 216 << extension->path().value(); | 195 << extension->path().value(); |
| 217 pending_manager->ExpectPolicyReinstallForCorruption(extension_id); | 196 pending_manager->ExpectPolicyReinstallForCorruption(extension_id); |
| 218 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); | 197 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); |
| 219 | 198 // Attempt to reinstall. |
| 220 net::BackoffEntry* backoff_entry = nullptr; | 199 policy_extension_reinstaller_->NotifyExtensionDisabledDueToCorruption(); |
| 221 auto iter = policy_reinstall_backoff_.find(extension_id); | |
| 222 if (iter != policy_reinstall_backoff_.end()) { | |
| 223 backoff_entry = iter->second.get(); | |
| 224 } else { | |
| 225 auto new_backoff_entry = | |
| 226 base::MakeUnique<net::BackoffEntry>(&kPolicyReinstallBackoffPolicy); | |
| 227 backoff_entry = new_backoff_entry.get(); | |
| 228 policy_reinstall_backoff_[extension_id] = std::move(new_backoff_entry); | |
| 229 } | |
| 230 backoff_entry->InformOfRequest(false); | |
| 231 | |
| 232 base::TimeDelta reinstall_delay = backoff_entry->GetTimeUntilRelease(); | |
| 233 if (g_reinstall_action_for_test) { | |
| 234 g_reinstall_action_for_test->Run(reinstall_delay); | |
| 235 } else { | |
| 236 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 237 FROM_HERE, base::Bind(&ExtensionService::CheckForExternalUpdates, | |
| 238 service->AsWeakPtr()), | |
| 239 reinstall_delay); | |
| 240 } | |
| 241 return; | 200 return; |
| 242 } | 201 } |
| 243 DLOG(WARNING) << "Disabling extension " << extension_id << " ('" | 202 DLOG(WARNING) << "Disabling extension " << extension_id << " ('" |
| 244 << extension->name() | 203 << extension->name() |
| 245 << "') due to content verification failure. In tests you " | 204 << "') due to content verification failure. In tests you " |
| 246 << "might want to use a ScopedIgnoreContentVerifierForTest " | 205 << "might want to use a ScopedIgnoreContentVerifierForTest " |
| 247 << "instance to prevent this."; | 206 << "instance to prevent this."; |
| 248 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); | 207 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); |
| 249 ExtensionPrefs::Get(context_)->IncrementCorruptedDisableCount(); | 208 ExtensionPrefs::Get(context_)->IncrementCorruptedDisableCount(); |
| 250 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionBecameDisabled", true); | 209 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionBecameDisabled", true); |
| 251 UMA_HISTOGRAM_ENUMERATION("Extensions.CorruptExtensionDisabledReason", | 210 UMA_HISTOGRAM_ENUMERATION("Extensions.CorruptExtensionDisabledReason", |
| 252 reason, ContentVerifyJob::FAILURE_REASON_MAX); | 211 reason, ContentVerifyJob::FAILURE_REASON_MAX); |
| 253 } else if (!base::ContainsKey(would_be_disabled_ids_, extension_id)) { | 212 } else if (!base::ContainsKey(would_be_disabled_ids_, extension_id)) { |
| 254 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionWouldBeDisabled", true); | 213 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionWouldBeDisabled", true); |
| 255 would_be_disabled_ids_.insert(extension_id); | 214 would_be_disabled_ids_.insert(extension_id); |
| 256 } | 215 } |
| 257 } | 216 } |
| 258 | 217 |
| 259 // static | 218 void ChromeContentVerifierDelegate::Shutdown() { |
| 260 void ChromeContentVerifierDelegate::set_policy_reinstall_action_for_test( | 219 policy_extension_reinstaller_.reset(); |
|
Devlin
2017/04/01 03:00:53
Document why this is important
lazyboy
2017/04/03 18:13:04
Done.
| |
| 261 base::Callback<void(base::TimeDelta delay)>* action) { | |
| 262 g_reinstall_action_for_test = action; | |
| 263 } | 220 } |
| 264 | 221 |
| 265 } // namespace extensions | 222 } // namespace extensions |
| OLD | NEW |