Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc

Issue 1903713002: Revert of Rate limit programmatic update checks for extensions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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/api/runtime/chrome_runtime_api_delegate.h" 5 #include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h"
6 6
7 #include <memory>
8 #include <string> 7 #include <string>
9 #include <utility> 8 #include <utility>
10 #include <vector>
11 9
12 #include "base/location.h" 10 #include "base/location.h"
13 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
14 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h" 13 #include "base/thread_task_runner_handle.h"
16 #include "base/time/time.h" 14 #include "base/time/time.h"
17 #include "build/build_config.h" 15 #include "build/build_config.h"
18 #include "chrome/browser/extensions/extension_service.h" 16 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_tab_util.h" 17 #include "chrome/browser/extensions/extension_tab_util.h"
20 #include "chrome/browser/extensions/updater/extension_updater.h" 18 #include "chrome/browser/extensions/updater/extension_updater.h"
21 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/ui/browser_finder.h" 20 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/browser/ui/browser_navigator.h" 21 #include "chrome/browser/ui/browser_navigator.h"
24 #include "chrome/browser/ui/browser_navigator_params.h" 22 #include "chrome/browser/ui/browser_navigator_params.h"
25 #include "chrome/browser/ui/browser_window.h" 23 #include "chrome/browser/ui/browser_window.h"
26 #include "components/update_client/update_query_params.h" 24 #include "components/update_client/update_query_params.h"
27 #include "content/public/browser/notification_service.h" 25 #include "content/public/browser/notification_service.h"
28 #include "extensions/browser/extension_registry.h"
29 #include "extensions/browser/extension_system.h" 26 #include "extensions/browser/extension_system.h"
30 #include "extensions/browser/notification_types.h" 27 #include "extensions/browser/notification_types.h"
31 #include "extensions/browser/warning_service.h" 28 #include "extensions/browser/warning_service.h"
32 #include "extensions/browser/warning_set.h" 29 #include "extensions/browser/warning_set.h"
33 #include "extensions/common/api/runtime.h" 30 #include "extensions/common/api/runtime.h"
34 #include "extensions/common/constants.h"
35 #include "net/base/backoff_entry.h"
36 31
37 #if defined(OS_CHROMEOS) 32 #if defined(OS_CHROMEOS)
38 #include "chromeos/dbus/dbus_thread_manager.h" 33 #include "chromeos/dbus/dbus_thread_manager.h"
39 #include "chromeos/dbus/power_manager_client.h" 34 #include "chromeos/dbus/power_manager_client.h"
40 #include "components/user_manager/user_manager.h" 35 #include "components/user_manager/user_manager.h"
41 #endif 36 #endif
42 37
43 using extensions::Extension; 38 using extensions::Extension;
44 using extensions::ExtensionSystem; 39 using extensions::ExtensionSystem;
45 using extensions::ExtensionUpdater; 40 using extensions::ExtensionUpdater;
46 41
47 using extensions::api::runtime::PlatformInfo; 42 using extensions::api::runtime::PlatformInfo;
48 43
49 namespace { 44 namespace {
50 45
51 const char kUpdateThrottled[] = "throttled"; 46 const char kUpdateThrottled[] = "throttled";
52 const char kUpdateNotFound[] = "no_update"; 47 const char kUpdateNotFound[] = "no_update";
53 const char kUpdateFound[] = "update_available"; 48 const char kUpdateFound[] = "update_available";
54 49
55 // If an extension reloads itself within this many miliseconds of reloading 50 // If an extension reloads itself within this many miliseconds of reloading
56 // itself, the reload is considered suspiciously fast. 51 // itself, the reload is considered suspiciously fast.
57 const int kFastReloadTime = 10000; 52 const int kFastReloadTime = 10000;
58 53
59 // After this many suspiciously fast consecutive reloads, an extension will get 54 // After this many suspiciously fast consecutive reloads, an extension will get
60 // disabled. 55 // disabled.
61 const int kFastReloadCount = 5; 56 const int kFastReloadCount = 5;
62 57
63 // The policy we use for exponential backoff of update check requests.
64 const net::BackoffEntry::Policy kBackoffPolicy = {
65 // num_errors_to_ignore
66 0,
67
68 // initial_delay_ms (note that we set 'always_use_initial_delay' to false
69 // below)
70 1000 * extensions::kDefaultUpdateFrequencySeconds,
71
72 // multiply_factor
73 1,
74
75 // jitter_factor
76 0.1,
77
78 // maximum_backoff_ms (-1 means no maximum)
79 -1,
80
81 // entry_lifetime_ms (-1 means never discard)
82 -1,
83
84 // always_use_initial_delay
85 false,
86 };
87
88 base::TickClock* g_test_clock = nullptr;
89
90 } // namespace 58 } // namespace
91 59
92 struct ChromeRuntimeAPIDelegate::UpdateCheckInfo {
93 public:
94 UpdateCheckInfo() {
95 if (g_test_clock)
96 backoff.reset(new net::BackoffEntry(&kBackoffPolicy, g_test_clock));
97 else
98 backoff.reset(new net::BackoffEntry(&kBackoffPolicy));
99 }
100
101 std::unique_ptr<net::BackoffEntry> backoff;
102 std::vector<UpdateCheckCallback> callbacks;
103 };
104
105 ChromeRuntimeAPIDelegate::ChromeRuntimeAPIDelegate( 60 ChromeRuntimeAPIDelegate::ChromeRuntimeAPIDelegate(
106 content::BrowserContext* context) 61 content::BrowserContext* context)
107 : browser_context_(context), 62 : browser_context_(context), registered_for_updates_(false) {
108 registered_for_updates_(false),
109 extension_registry_observer_(this) {
110 registrar_.Add(this, 63 registrar_.Add(this,
111 extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND, 64 extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND,
112 content::NotificationService::AllSources()); 65 content::NotificationService::AllSources());
113 extension_registry_observer_.Add(
114 extensions::ExtensionRegistry::Get(browser_context_));
115 } 66 }
116 67
117 ChromeRuntimeAPIDelegate::~ChromeRuntimeAPIDelegate() { 68 ChromeRuntimeAPIDelegate::~ChromeRuntimeAPIDelegate() {
118 } 69 }
119 70
120 // static
121 void ChromeRuntimeAPIDelegate::set_tick_clock_for_tests(
122 base::TickClock* clock) {
123 g_test_clock = clock;
124 }
125
126 void ChromeRuntimeAPIDelegate::AddUpdateObserver( 71 void ChromeRuntimeAPIDelegate::AddUpdateObserver(
127 extensions::UpdateObserver* observer) { 72 extensions::UpdateObserver* observer) {
128 registered_for_updates_ = true; 73 registered_for_updates_ = true;
129 ExtensionSystem::Get(browser_context_) 74 ExtensionSystem::Get(browser_context_)
130 ->extension_service() 75 ->extension_service()
131 ->AddUpdateObserver(observer); 76 ->AddUpdateObserver(observer);
132 } 77 }
133 78
134 void ChromeRuntimeAPIDelegate::RemoveUpdateObserver( 79 void ChromeRuntimeAPIDelegate::RemoveUpdateObserver(
135 extensions::UpdateObserver* observer) { 80 extensions::UpdateObserver* observer) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 145
201 bool ChromeRuntimeAPIDelegate::CheckForUpdates( 146 bool ChromeRuntimeAPIDelegate::CheckForUpdates(
202 const std::string& extension_id, 147 const std::string& extension_id,
203 const UpdateCheckCallback& callback) { 148 const UpdateCheckCallback& callback) {
204 ExtensionSystem* system = ExtensionSystem::Get(browser_context_); 149 ExtensionSystem* system = ExtensionSystem::Get(browser_context_);
205 ExtensionService* service = system->extension_service(); 150 ExtensionService* service = system->extension_service();
206 ExtensionUpdater* updater = service->updater(); 151 ExtensionUpdater* updater = service->updater();
207 if (!updater) { 152 if (!updater) {
208 return false; 153 return false;
209 } 154 }
210 155 if (!updater->CheckExtensionSoon(
211 UpdateCheckInfo& info = update_check_info_[extension_id]; 156 extension_id,
212 157 base::Bind(&ChromeRuntimeAPIDelegate::UpdateCheckComplete,
213 // If not enough time has elapsed, or we have 10 or more outstanding calls, 158 base::Unretained(this),
214 // return a status of throttled. 159 extension_id))) {
215 if (info.backoff->ShouldRejectRequest() || info.callbacks.size() >= 10) {
216 base::ThreadTaskRunnerHandle::Get()->PostTask( 160 base::ThreadTaskRunnerHandle::Get()->PostTask(
217 FROM_HERE, 161 FROM_HERE,
218 base::Bind(callback, UpdateCheckResult(true, kUpdateThrottled, ""))); 162 base::Bind(callback, UpdateCheckResult(true, kUpdateThrottled, "")));
219 } else { 163 } else {
220 info.callbacks.push_back(callback); 164 UpdateCallbackList& callbacks = pending_update_checks_[extension_id];
221 updater->CheckExtensionSoon( 165 callbacks.push_back(callback);
222 extension_id, base::Bind(&ChromeRuntimeAPIDelegate::UpdateCheckComplete,
223 base::Unretained(this), extension_id));
224 } 166 }
225 return true; 167 return true;
226 } 168 }
227 169
228 void ChromeRuntimeAPIDelegate::OpenURL(const GURL& uninstall_url) { 170 void ChromeRuntimeAPIDelegate::OpenURL(const GURL& uninstall_url) {
229 Profile* profile = Profile::FromBrowserContext(browser_context_); 171 Profile* profile = Profile::FromBrowserContext(browser_context_);
230 Browser* browser = chrome::FindLastActiveWithProfile(profile); 172 Browser* browser = chrome::FindLastActiveWithProfile(profile);
231 if (!browser) 173 if (!browser)
232 browser = new Browser(Browser::CreateParams(profile)); 174 browser = new Browser(Browser::CreateParams(profile));
233 175
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 DCHECK(type == extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND); 252 DCHECK(type == extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND);
311 typedef const std::pair<std::string, Version> UpdateDetails; 253 typedef const std::pair<std::string, Version> UpdateDetails;
312 const std::string& id = content::Details<UpdateDetails>(details)->first; 254 const std::string& id = content::Details<UpdateDetails>(details)->first;
313 const Version& version = content::Details<UpdateDetails>(details)->second; 255 const Version& version = content::Details<UpdateDetails>(details)->second;
314 if (version.IsValid()) { 256 if (version.IsValid()) {
315 CallUpdateCallbacks( 257 CallUpdateCallbacks(
316 id, UpdateCheckResult(true, kUpdateFound, version.GetString())); 258 id, UpdateCheckResult(true, kUpdateFound, version.GetString()));
317 } 259 }
318 } 260 }
319 261
320 void ChromeRuntimeAPIDelegate::OnExtensionInstalled(
321 content::BrowserContext* browser_context,
322 const Extension* extension,
323 bool is_update) {
324 if (!is_update)
325 return;
326 auto info = update_check_info_.find(extension->id());
327 if (info != update_check_info_.end()) {
328 info->second.backoff->Reset();
329 }
330 }
331
332 void ChromeRuntimeAPIDelegate::UpdateCheckComplete( 262 void ChromeRuntimeAPIDelegate::UpdateCheckComplete(
333 const std::string& extension_id) { 263 const std::string& extension_id) {
334 ExtensionSystem* system = ExtensionSystem::Get(browser_context_); 264 ExtensionSystem* system = ExtensionSystem::Get(browser_context_);
335 ExtensionService* service = system->extension_service(); 265 ExtensionService* service = system->extension_service();
336 const Extension* update = service->GetPendingExtensionUpdate(extension_id); 266 const Extension* update = service->GetPendingExtensionUpdate(extension_id);
337 UpdateCheckInfo& info = update_check_info_[extension_id];
338
339 // We always inform the BackoffEntry of a "failure" here, because we only
340 // want to consider an update check request a success from a throttling
341 // standpoint once the extension goes on to actually update to a new
342 // version. See OnExtensionInstalled for where we reset the BackoffEntry.
343 info.backoff->InformOfRequest(false);
344
345 if (update) { 267 if (update) {
346 CallUpdateCallbacks( 268 CallUpdateCallbacks(
347 extension_id, 269 extension_id,
348 UpdateCheckResult(true, kUpdateFound, update->VersionString())); 270 UpdateCheckResult(true, kUpdateFound, update->VersionString()));
349 } else { 271 } else {
350 CallUpdateCallbacks(extension_id, 272 CallUpdateCallbacks(extension_id,
351 UpdateCheckResult(true, kUpdateNotFound, "")); 273 UpdateCheckResult(true, kUpdateNotFound, ""));
352 } 274 }
353 } 275 }
354 276
355 void ChromeRuntimeAPIDelegate::CallUpdateCallbacks( 277 void ChromeRuntimeAPIDelegate::CallUpdateCallbacks(
356 const std::string& extension_id, 278 const std::string& extension_id,
357 const UpdateCheckResult& result) { 279 const UpdateCheckResult& result) {
358 auto it = update_check_info_.find(extension_id); 280 UpdateCallbackList callbacks = pending_update_checks_[extension_id];
359 if (it == update_check_info_.end()) 281 pending_update_checks_.erase(extension_id);
360 return; 282 for (UpdateCallbackList::const_iterator iter = callbacks.begin();
361 std::vector<UpdateCheckCallback> callbacks; 283 iter != callbacks.end();
362 it->second.callbacks.swap(callbacks); 284 ++iter) {
363 for (const auto& callback : callbacks) { 285 const UpdateCheckCallback& callback = *iter;
364 callback.Run(result); 286 callback.Run(result);
365 } 287 }
366 } 288 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698