| 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" |
| 26 #include "extensions/browser/extension_prefs.h" | 27 #include "extensions/browser/extension_prefs.h" |
| 27 #include "extensions/browser/extension_registry.h" | 28 #include "extensions/browser/extension_registry.h" |
| 28 #include "extensions/browser/extension_system.h" | 29 #include "extensions/browser/extension_system.h" |
| 29 #include "extensions/browser/management_policy.h" | 30 #include "extensions/browser/management_policy.h" |
| 30 #include "extensions/common/constants.h" | 31 #include "extensions/common/constants.h" |
| 31 #include "extensions/common/extension.h" | 32 #include "extensions/common/extension.h" |
| 32 #include "extensions/common/extension_urls.h" | 33 #include "extensions/common/extension_urls.h" |
| 33 #include "extensions/common/extensions_client.h" | 34 #include "extensions/common/extensions_client.h" |
| 34 #include "extensions/common/manifest.h" | 35 #include "extensions/common/manifest.h" |
| 35 #include "extensions/common/manifest_url_handlers.h" | 36 #include "extensions/common/manifest_url_handlers.h" |
| 36 #include "net/base/backoff_entry.h" | 37 #include "net/base/backoff_entry.h" |
| 37 #include "net/base/escape.h" | 38 #include "net/base/escape.h" |
| 38 | 39 |
| 39 #if defined(OS_CHROMEOS) | 40 #if defined(OS_CHROMEOS) |
| 40 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h" | 41 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h" |
| 41 #endif | 42 #endif |
| 42 | 43 |
| 43 namespace { | 44 namespace { |
| 44 | 45 |
| 45 const char kContentVerificationExperimentName[] = | 46 const char kContentVerificationExperimentName[] = |
| 46 "ExtensionContentVerification"; | 47 "ExtensionContentVerification"; |
| 47 | 48 |
| 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 | 49 |
| 75 } // namespace | 50 } // namespace |
| 76 | 51 |
| 77 namespace extensions { | 52 namespace extensions { |
| 78 | 53 |
| 79 // static | 54 // static |
| 80 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::GetDefaultMode() { | 55 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::GetDefaultMode() { |
| 81 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 56 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 82 | 57 |
| 83 Mode experiment_value; | 58 Mode experiment_value; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 } | 103 } |
| 129 | 104 |
| 130 // We don't want to allow the command-line flags to eg disable enforcement | 105 // 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 | 106 // 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. | 107 // the command line flags. So return the more restrictive of the 2 values. |
| 133 return std::max(experiment_value, cmdline_value); | 108 return std::max(experiment_value, cmdline_value); |
| 134 } | 109 } |
| 135 | 110 |
| 136 ChromeContentVerifierDelegate::ChromeContentVerifierDelegate( | 111 ChromeContentVerifierDelegate::ChromeContentVerifierDelegate( |
| 137 content::BrowserContext* context) | 112 content::BrowserContext* context) |
| 138 : context_(context), default_mode_(GetDefaultMode()) {} | 113 : context_(context), |
| 114 default_mode_(GetDefaultMode()), |
| 115 policy_extension_reinstaller_( |
| 116 base::MakeUnique<PolicyExtensionReinstaller>(context_)) {} |
| 139 | 117 |
| 140 ChromeContentVerifierDelegate::~ChromeContentVerifierDelegate() { | 118 ChromeContentVerifierDelegate::~ChromeContentVerifierDelegate() { |
| 141 } | 119 } |
| 142 | 120 |
| 143 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::ShouldBeVerified( | 121 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::ShouldBeVerified( |
| 144 const Extension& extension) { | 122 const Extension& extension) { |
| 145 #if defined(OS_CHROMEOS) | 123 #if defined(OS_CHROMEOS) |
| 146 if (ExtensionAssetsManagerChromeOS::IsSharedInstall(&extension)) | 124 if (ExtensionAssetsManagerChromeOS::IsSharedInstall(&extension)) |
| 147 return ContentVerifierDelegate::ENFORCE_STRICT; | 125 return ContentVerifierDelegate::ENFORCE_STRICT; |
| 148 #endif | 126 #endif |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 if (system->management_policy()->MustRemainEnabled(extension, NULL)) { | 187 if (system->management_policy()->MustRemainEnabled(extension, NULL)) { |
| 210 PendingExtensionManager* pending_manager = | 188 PendingExtensionManager* pending_manager = |
| 211 service->pending_extension_manager(); | 189 service->pending_extension_manager(); |
| 212 if (pending_manager->IsPolicyReinstallForCorruptionExpected(extension_id)) | 190 if (pending_manager->IsPolicyReinstallForCorruptionExpected(extension_id)) |
| 213 return; | 191 return; |
| 214 SYSLOG(WARNING) << "Corruption detected in policy extension " | 192 SYSLOG(WARNING) << "Corruption detected in policy extension " |
| 215 << extension_id << " installed at: " | 193 << extension_id << " installed at: " |
| 216 << extension->path().value(); | 194 << extension->path().value(); |
| 217 pending_manager->ExpectPolicyReinstallForCorruption(extension_id); | 195 pending_manager->ExpectPolicyReinstallForCorruption(extension_id); |
| 218 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); | 196 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); |
| 219 | 197 // Attempt to reinstall. |
| 220 net::BackoffEntry* backoff_entry = nullptr; | 198 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; | 199 return; |
| 242 } | 200 } |
| 243 DLOG(WARNING) << "Disabling extension " << extension_id << " ('" | 201 DLOG(WARNING) << "Disabling extension " << extension_id << " ('" |
| 244 << extension->name() | 202 << extension->name() |
| 245 << "') due to content verification failure. In tests you " | 203 << "') due to content verification failure. In tests you " |
| 246 << "might want to use a ScopedIgnoreContentVerifierForTest " | 204 << "might want to use a ScopedIgnoreContentVerifierForTest " |
| 247 << "instance to prevent this."; | 205 << "instance to prevent this."; |
| 248 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); | 206 service->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); |
| 249 ExtensionPrefs::Get(context_)->IncrementCorruptedDisableCount(); | 207 ExtensionPrefs::Get(context_)->IncrementCorruptedDisableCount(); |
| 250 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionBecameDisabled", true); | 208 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionBecameDisabled", true); |
| 251 UMA_HISTOGRAM_ENUMERATION("Extensions.CorruptExtensionDisabledReason", | 209 UMA_HISTOGRAM_ENUMERATION("Extensions.CorruptExtensionDisabledReason", |
| 252 reason, ContentVerifyJob::FAILURE_REASON_MAX); | 210 reason, ContentVerifyJob::FAILURE_REASON_MAX); |
| 253 } else if (!base::ContainsKey(would_be_disabled_ids_, extension_id)) { | 211 } else if (!base::ContainsKey(would_be_disabled_ids_, extension_id)) { |
| 254 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionWouldBeDisabled", true); | 212 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionWouldBeDisabled", true); |
| 255 would_be_disabled_ids_.insert(extension_id); | 213 would_be_disabled_ids_.insert(extension_id); |
| 256 } | 214 } |
| 257 } | 215 } |
| 258 | 216 |
| 259 // static | 217 void ChromeContentVerifierDelegate::Shutdown() { |
| 260 void ChromeContentVerifierDelegate::set_policy_reinstall_action_for_test( | 218 // Shut down |policy_extension_reinstaller_| on its creation thread. |this| |
| 261 base::Callback<void(base::TimeDelta delay)>* action) { | 219 // can be destroyed through InfoMap on IO thread, we do not want to destroy |
| 262 g_reinstall_action_for_test = action; | 220 // |policy_extension_reinstaller_| there. |
| 221 policy_extension_reinstaller_.reset(); |
| 263 } | 222 } |
| 264 | 223 |
| 265 } // namespace extensions | 224 } // namespace extensions |
| OLD | NEW |