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

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

Issue 264743014: Move chrome.runtime to //extensions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/chrome_runtime_api_delegate.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/metrics/histogram.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_warning_service.h"
13 #include "chrome/browser/extensions/extension_warning_set.h"
14 #include "chrome/browser/extensions/updater/extension_updater.h"
15 #include "chrome/browser/omaha_query_params/omaha_query_params.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/browser_finder.h"
18 #include "chrome/browser/ui/browser_navigator.h"
19 #include "chrome/browser/ui/browser_window.h"
20 #include "content/public/browser/notification_service.h"
21 #include "extensions/browser/extension_system.h"
22
23 #if defined(OS_CHROMEOS)
24 #include "chrome/browser/chromeos/login/user_manager.h"
25 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/power_manager_client.h"
27 #endif
28
29 using extensions::Extension;
30 using extensions::ExtensionSystem;
31 using extensions::ExtensionUpdater;
32 using extensions::RuntimeAPI;
33
34 using extensions::core_api::runtime::GetPlatformInfo::Results::PlatformInfo;
35
36 namespace {
37
38 const char kUpdatesDisabledError[] = "Autoupdate is not enabled.";
39
40 const char kUpdateThrottled[] = "throttled";
41 const char kUpdateNotFound[] = "no_update";
42 const char kUpdateFound[] = "update_available";
43
44 // If an extension reloads itself within this many miliseconds of reloading
45 // itself, the reload is considered suspiciously fast.
46 const int kFastReloadTime = 10000;
47
48 // After this many suspiciously fast consecutive reloads, an extension will get
49 // disabled.
50 const int kFastReloadCount = 5;
51
52 } // namespace
53
54 ChromeRuntimeAPIDelegate::ChromeRuntimeAPIDelegate(
55 content::BrowserContext* context)
56 : browser_context_(context), registered_for_updates_(false) {
57 registrar_.Add(this,
58 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND,
59 content::NotificationService::AllSources());
60 }
61
62 ChromeRuntimeAPIDelegate::~ChromeRuntimeAPIDelegate() {
63 }
64
65 void ChromeRuntimeAPIDelegate::RegisterUpdateObserver(
not at google - send to devlin 2014/05/05 19:26:15 why is this called "RegisterUpdateObserver" while
Ken Rockot(use gerrit already) 2014/05/05 21:08:07 I don't have a good answer. Changed.
66 extensions::UpdateObserver* observer) {
67 registered_for_updates_ = true;
68 ExtensionSystem::Get(browser_context_)
69 ->extension_service()
70 ->AddUpdateObserver(observer);
71 }
72
73 void ChromeRuntimeAPIDelegate::UnregisterUpdateObserver(
74 extensions::UpdateObserver* observer) {
75 if (registered_for_updates_) {
76 ExtensionSystem::Get(browser_context_)
77 ->extension_service()
78 ->RemoveUpdateObserver(observer);
79 }
80 }
81
82 base::Version ChromeRuntimeAPIDelegate::GetOldExtensionVersion(
83 const Extension* extension) {
84 // Get the previous version to check if this is an upgrade.
85 ExtensionService* service =
86 ExtensionSystem::Get(browser_context_)->extension_service();
87 const Extension* old = service->GetExtensionById(extension->id(), true);
88 if (old)
89 return *old->version();
90 return base::Version();
91 }
92
93 void ChromeRuntimeAPIDelegate::MaybeReloadExtension(
94 const std::string& extension_id) {
95 std::pair<base::TimeTicks, int>& reload_info =
96 last_reload_time_[extension_id];
97 base::TimeTicks now = base::TimeTicks::Now();
98 if (reload_info.first.is_null() ||
99 (now - reload_info.first).InMilliseconds() > kFastReloadTime) {
100 reload_info.second = 0;
101 } else {
102 reload_info.second++;
103 }
104 if (!reload_info.first.is_null()) {
105 UMA_HISTOGRAM_LONG_TIMES("Extensions.RuntimeReloadTime",
106 now - reload_info.first);
107 }
108 UMA_HISTOGRAM_COUNTS_100("Extensions.RuntimeReloadFastCount",
109 reload_info.second);
110 reload_info.first = now;
111
112 ExtensionService* service =
113 ExtensionSystem::Get(browser_context_)->extension_service();
114 if (reload_info.second >= kFastReloadCount) {
115 // Unloading an extension clears all warnings, so first terminate the
116 // extension, and then add the warning. Since this is called from an
117 // extension function unloading the extension has to be done
118 // asynchronously. Fortunately PostTask guarentees FIFO order so just
119 // post both tasks.
120 base::MessageLoop::current()->PostTask(
121 FROM_HERE,
122 base::Bind(&ExtensionService::TerminateExtension,
123 service->AsWeakPtr(),
124 extension_id));
125 extensions::ExtensionWarningSet warnings;
126 warnings.insert(
127 extensions::ExtensionWarning::CreateReloadTooFrequentWarning(
128 extension_id));
129 base::MessageLoop::current()->PostTask(
130 FROM_HERE,
131 base::Bind(&extensions::ExtensionWarningService::NotifyWarningsOnUI,
132 browser_context_,
133 warnings));
134 } else {
135 // We can't call ReloadExtension directly, since when this method finishes
136 // it tries to decrease the reference count for the extension, which fails
137 // if the extension has already been reloaded; so instead we post a task.
138 base::MessageLoop::current()->PostTask(
139 FROM_HERE,
140 base::Bind(&ExtensionService::ReloadExtension,
141 service->AsWeakPtr(),
142 extension_id));
143 }
144 }
145
146 bool ChromeRuntimeAPIDelegate::RequestUpdateCheck(
147 const std::string& extension_id,
148 const RuntimeAPI::UpdateCheckCallback& callback) {
149 ExtensionSystem* system = ExtensionSystem::Get(browser_context_);
150 ExtensionService* service = system->extension_service();
151 ExtensionUpdater* updater = service->updater();
152 if (!updater) {
153 return false;
154 }
155 if (!updater->CheckExtensionSoon(
156 extension_id,
157 base::Bind(&ChromeRuntimeAPIDelegate::UpdateCheckComplete,
158 base::Unretained(this),
159 extension_id))) {
160 base::MessageLoop::current()->PostTask(
161 FROM_HERE,
162 base::Bind(callback,
163 RuntimeAPI::UpdateCheckResult(true, kUpdateThrottled, "")));
164 } else {
165 UpdateCallbackList& callbacks = pending_update_checks_[extension_id];
166 callbacks.push_back(callback);
167 }
168 return true;
169 }
170
171 void ChromeRuntimeAPIDelegate::HandleUninstall(const std::string& extension_id,
172 const GURL& uninstall_url) {
173 Profile* profile = Profile::FromBrowserContext(browser_context_);
174 Browser* browser =
175 chrome::FindLastActiveWithProfile(profile, chrome::GetActiveDesktop());
176 if (!browser)
177 browser =
178 new Browser(Browser::CreateParams(profile, chrome::GetActiveDesktop()));
179
180 chrome::NavigateParams params(
181 browser, uninstall_url, content::PAGE_TRANSITION_CLIENT_REDIRECT);
182 params.disposition = NEW_FOREGROUND_TAB;
183 params.user_gesture = false;
184 chrome::Navigate(&params);
185 }
186
187 bool ChromeRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) {
188 const char* os = chrome::OmahaQueryParams::GetOS();
189 if (strcmp(os, "mac") == 0) {
190 info->os = PlatformInfo::OS_MAC_;
191 } else if (strcmp(os, "win") == 0) {
192 info->os = PlatformInfo::OS_WIN_;
193 } else if (strcmp(os, "android") == 0) {
194 info->os = PlatformInfo::OS_ANDROID_;
195 } else if (strcmp(os, "cros") == 0) {
196 info->os = PlatformInfo::OS_CROS_;
197 } else if (strcmp(os, "linux") == 0) {
198 info->os = PlatformInfo::OS_LINUX_;
199 } else if (strcmp(os, "openbsd") == 0) {
200 info->os = PlatformInfo::OS_OPENBSD_;
201 } else {
202 NOTREACHED();
203 return false;
204 }
205
206 const char* arch = chrome::OmahaQueryParams::GetArch();
207 if (strcmp(arch, "arm") == 0) {
208 info->arch = PlatformInfo::ARCH_ARM;
209 } else if (strcmp(arch, "x86") == 0) {
210 info->arch = PlatformInfo::ARCH_X86_32;
211 } else if (strcmp(arch, "x64") == 0) {
212 info->arch = PlatformInfo::ARCH_X86_64;
213 } else {
214 NOTREACHED();
215 return false;
216 }
217
218 const char* nacl_arch = chrome::OmahaQueryParams::GetNaclArch();
219 if (strcmp(nacl_arch, "arm") == 0) {
220 info->nacl_arch = PlatformInfo::NACL_ARCH_ARM;
221 } else if (strcmp(nacl_arch, "x86-32") == 0) {
222 info->nacl_arch = PlatformInfo::NACL_ARCH_X86_32;
223 } else if (strcmp(nacl_arch, "x86-64") == 0) {
224 info->nacl_arch = PlatformInfo::NACL_ARCH_X86_64;
225 } else {
226 NOTREACHED();
227 return false;
228 }
229
230 return true;
231 }
232
233 bool ChromeRuntimeAPIDelegate::RequestRestart(std::string* error_message) {
234 #if defined(OS_CHROMEOS)
235 if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp()) {
236 chromeos::DBusThreadManager::Get()
237 ->GetPowerManagerClient()
238 ->RequestRestart();
239 return true;
240 }
241 #endif
242 *error_message = "Function available only for ChromeOS kiosk mode.";
243 return false;
244 }
245
246 void ChromeRuntimeAPIDelegate::Observe(
247 int type,
248 const content::NotificationSource& source,
249 const content::NotificationDetails& details) {
250 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND);
251 typedef const std::pair<std::string, Version> UpdateDetails;
252 const std::string& id = content::Details<UpdateDetails>(details)->first;
253 const Version& version = content::Details<UpdateDetails>(details)->second;
254 CallUpdateCallbacks(
255 id,
256 RuntimeAPI::UpdateCheckResult(true, kUpdateFound, version.GetString()));
257 }
258
259 void ChromeRuntimeAPIDelegate::UpdateCheckComplete(
260 const std::string& extension_id) {
261 ExtensionSystem* system = ExtensionSystem::Get(browser_context_);
262 ExtensionService* service = system->extension_service();
263 const Extension* update = service->GetPendingExtensionUpdate(extension_id);
264 if (update) {
265 CallUpdateCallbacks(extension_id,
266 RuntimeAPI::UpdateCheckResult(
267 true, kUpdateFound, update->VersionString()));
268 } else {
269 CallUpdateCallbacks(
270 extension_id, RuntimeAPI::UpdateCheckResult(true, kUpdateNotFound, ""));
271 }
272 }
273
274 void ChromeRuntimeAPIDelegate::CallUpdateCallbacks(
275 const std::string& extension_id,
276 const RuntimeAPI::UpdateCheckResult& result) {
277 UpdateCallbackList callbacks = pending_update_checks_[extension_id];
278 pending_update_checks_.erase(extension_id);
279 for (UpdateCallbackList::const_iterator iter = callbacks.begin();
280 iter != callbacks.end();
281 ++iter) {
282 const RuntimeAPI::UpdateCheckCallback& callback = *iter;
283 callback.Run(result);
284 }
285 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698