Chromium Code Reviews

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

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

Powered by Google App Engine