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

Side by Side Diff: extensions/browser/api/runtime/runtime_api.cc

Issue 1970613003: Add a new app API to enable watchdog behavior restarts in kiosk apps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unneeded include and forward declare Created 4 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
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 "extensions/browser/api/runtime/runtime_api.h" 5 #include "extensions/browser/api/runtime/runtime_api.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/strings/string_number_conversions.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "base/version.h" 15 #include "base/version.h"
15 #include "content/public/browser/browser_context.h" 16 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/child_process_security_policy.h" 17 #include "content/public/browser/child_process_security_policy.h"
17 #include "content/public/browser/notification_service.h" 18 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/render_frame_host.h" 19 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/render_process_host.h" 20 #include "content/public/browser/render_process_host.h"
20 #include "extensions/browser/api/runtime/runtime_api_delegate.h" 21 #include "extensions/browser/api/runtime/runtime_api_delegate.h"
21 #include "extensions/browser/event_router.h" 22 #include "extensions/browser/event_router.h"
22 #include "extensions/browser/extension_host.h" 23 #include "extensions/browser/extension_host.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 "pending_on_installed_event_dispatch_info"; 70 "pending_on_installed_event_dispatch_info";
70 71
71 // Previously installed version number. 72 // Previously installed version number.
72 const char kPrefPreviousVersion[] = "previous_version"; 73 const char kPrefPreviousVersion[] = "previous_version";
73 74
74 // The name of the directory to be returned by getPackageDirectoryEntry. This 75 // The name of the directory to be returned by getPackageDirectoryEntry. This
75 // particular value does not matter to user code, but is chosen for consistency 76 // particular value does not matter to user code, but is chosen for consistency
76 // with the equivalent Pepper API. 77 // with the equivalent Pepper API.
77 const char kPackageDirectoryPath[] = "crxfs"; 78 const char kPackageDirectoryPath[] = "crxfs";
78 79
80 // Preferece keys for storing the last successful restart on watchdog requests.
81 const char kPrefRestartOnWatchdogTime[] = "restart_on_watchdog_time_prefs";
82 const char kPrefLastRestartTime[] = "last_restart_on_watchdog_time";
83
84 const int kMinDurationBetweenSuccessiveRestartsHours = 3;
85
79 void DispatchOnStartupEventImpl(BrowserContext* browser_context, 86 void DispatchOnStartupEventImpl(BrowserContext* browser_context,
80 const std::string& extension_id, 87 const std::string& extension_id,
81 bool first_call, 88 bool first_call,
82 ExtensionHost* host) { 89 ExtensionHost* host) {
83 // A NULL host from the LazyBackgroundTaskQueue means the page failed to 90 // A NULL host from the LazyBackgroundTaskQueue means the page failed to
84 // load. Give up. 91 // load. Give up.
85 if (!host && !first_call) 92 if (!host && !first_call)
86 return; 93 return;
87 94
88 // Don't send onStartup events to incognito browser contexts. 95 // Don't send onStartup events to incognito browser contexts.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 156
150 template <> 157 template <>
151 void BrowserContextKeyedAPIFactory<RuntimeAPI>::DeclareFactoryDependencies() { 158 void BrowserContextKeyedAPIFactory<RuntimeAPI>::DeclareFactoryDependencies() {
152 DependsOn(ProcessManagerFactory::GetInstance()); 159 DependsOn(ProcessManagerFactory::GetInstance());
153 } 160 }
154 161
155 RuntimeAPI::RuntimeAPI(content::BrowserContext* context) 162 RuntimeAPI::RuntimeAPI(content::BrowserContext* context)
156 : browser_context_(context), 163 : browser_context_(context),
157 dispatch_chrome_updated_event_(false), 164 dispatch_chrome_updated_event_(false),
158 extension_registry_observer_(this), 165 extension_registry_observer_(this),
159 process_manager_observer_(this) { 166 process_manager_observer_(this),
167 minimum_duration_between_restarts_(base::TimeDelta::FromHours(
168 kMinDurationBetweenSuccessiveRestartsHours)) {
160 // RuntimeAPI is redirected in incognito, so |browser_context_| is never 169 // RuntimeAPI is redirected in incognito, so |browser_context_| is never
161 // incognito. 170 // incognito.
162 DCHECK(!browser_context_->IsOffTheRecord()); 171 DCHECK(!browser_context_->IsOffTheRecord());
163 172
164 registrar_.Add(this, 173 registrar_.Add(this,
165 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, 174 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
166 content::Source<BrowserContext>(context)); 175 content::Source<BrowserContext>(context));
167 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); 176 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
168 process_manager_observer_.Add(ProcessManager::Get(browser_context_)); 177 process_manager_observer_.Add(ProcessManager::Get(browser_context_));
169 178
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 } 323 }
315 324
316 bool RuntimeAPI::GetPlatformInfo(runtime::PlatformInfo* info) { 325 bool RuntimeAPI::GetPlatformInfo(runtime::PlatformInfo* info) {
317 return delegate_->GetPlatformInfo(info); 326 return delegate_->GetPlatformInfo(info);
318 } 327 }
319 328
320 bool RuntimeAPI::RestartDevice(std::string* error_message) { 329 bool RuntimeAPI::RestartDevice(std::string* error_message) {
321 return delegate_->RestartDevice(error_message); 330 return delegate_->RestartDevice(error_message);
322 } 331 }
323 332
333 void RuntimeAPI::RestartDeviceOnWatchdogTimeout(
334 const Extension* extension,
335 int seconds,
336 const OnWatchdogTimeoutCallback& callback) {
337 if (seconds == -1) {
338 watchdog_timer_.Stop();
339 callback.Run(false, "Restart on watchdog was canceled.");
340 return;
341 }
342
343 watchdog_timer_.Stop();
xiyuan 2016/05/13 17:56:15 |watchdog_timer_| is a per-profile resource. We pr
afakhry 2016/05/14 01:27:35 Done.
344 watchdog_timer_.Start(
345 FROM_HERE, base::TimeDelta::FromSeconds(seconds),
346 base::Bind(&RuntimeAPI::OnRestartWatchdogTimeout, base::Unretained(this),
xiyuan 2016/05/13 17:56:15 nit: There is another Start on OneShotTimer interf
afakhry 2016/05/14 01:27:35 Yes, the problem with that interface is that I won
xiyuan 2016/05/16 18:25:17 Acknowledged.
347 extension, callback));
348 }
349
324 bool RuntimeAPI::OpenOptionsPage(const Extension* extension) { 350 bool RuntimeAPI::OpenOptionsPage(const Extension* extension) {
325 return delegate_->OpenOptionsPage(extension); 351 return delegate_->OpenOptionsPage(extension);
326 } 352 }
327 353
354 void RuntimeAPI::OnRestartWatchdogTimeout(
355 const Extension* extension,
356 const OnWatchdogTimeoutCallback& callback) {
357 // Throttle restart requests that are received too soon successively.
358 base::TimeTicks now = base::TimeTicks::Now();
xiyuan 2016/05/13 17:56:15 Time is always a trick topic. base::TimeTicks is a
afakhry 2016/05/14 01:27:35 Thanks for providing the link. Changed it to base:
359 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
xiyuan 2016/05/13 17:56:15 Sorry for flipping on my suggestion. Let's store t
afakhry 2016/05/14 01:27:35 Done.
360 DCHECK(prefs);
361
362 const base::DictionaryValue* restart_on_watchdog_prefs = nullptr;
363 if (prefs->ReadPrefAsDictionary(extension->id(), kPrefRestartOnWatchdogTime,
364 &restart_on_watchdog_prefs)) {
365 double last_restart_ticks = 0.0;
366 if (restart_on_watchdog_prefs->GetDouble(kPrefLastRestartTime,
367 &last_restart_ticks)) {
368 base::TimeTicks last_time = base::TimeTicks::FromInternalValue(
369 static_cast<int64_t>(last_restart_ticks));
370 if ((now - last_time) < minimum_duration_between_restarts_) {
371 callback.Run(false, "Error: Called too soon since the last restart.");
372 // TODO(afakhry): Figure out what to do here. Do we restart later?
xiyuan 2016/05/13 17:56:15 We should still reboot but after the minimum reboo
afakhry 2016/05/14 01:27:35 Done. Rebooting after the minimum reboot time has
373 return;
374 }
375 }
376 }
377
378 std::string error_message;
379 const bool success = delegate_->RestartDevice(&error_message);
380
381 if (success) {
382 // Store |now| as the last successful restart request time.
383 base::DictionaryValue* prefs_to_update = new base::DictionaryValue();
384 prefs_to_update->SetDouble(kPrefLastRestartTime,
385 static_cast<double>(now.ToInternalValue()));
386 prefs->UpdateExtensionPref(extension->id(), kPrefRestartOnWatchdogTime,
387 prefs_to_update);
388 }
389
390 callback.Run(success, error_message);
391 }
392
328 /////////////////////////////////////////////////////////////////////////////// 393 ///////////////////////////////////////////////////////////////////////////////
329 394
330 // static 395 // static
331 void RuntimeEventRouter::DispatchOnStartupEvent( 396 void RuntimeEventRouter::DispatchOnStartupEvent(
332 content::BrowserContext* context, 397 content::BrowserContext* context,
333 const std::string& extension_id) { 398 const std::string& extension_id) {
334 DispatchOnStartupEventImpl(context, extension_id, true, NULL); 399 DispatchOnStartupEventImpl(context, extension_id, true, NULL);
335 } 400 }
336 401
337 // static 402 // static
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 std::string message; 609 std::string message;
545 bool result = 610 bool result =
546 RuntimeAPI::GetFactoryInstance()->Get(browser_context())->RestartDevice( 611 RuntimeAPI::GetFactoryInstance()->Get(browser_context())->RestartDevice(
547 &message); 612 &message);
548 if (!result) { 613 if (!result) {
549 return RespondNow(Error(message)); 614 return RespondNow(Error(message));
550 } 615 }
551 return RespondNow(NoArguments()); 616 return RespondNow(NoArguments());
552 } 617 }
553 618
619 ExtensionFunction::ResponseAction RuntimeRestartOnWatchdogFunction::Run() {
620 std::unique_ptr<api::runtime::RestartOnWatchdog::Params> params(
621 api::runtime::RestartOnWatchdog::Params::Create(*args_));
622 EXTENSION_FUNCTION_VALIDATE(params.get());
xiyuan 2016/05/13 17:56:15 Check ExtensionsBrowserClient::Get()->IsRunningInF
afakhry 2016/05/14 01:27:35 I added a TODO here instead, because I'll need mor
afakhry 2016/05/17 18:38:31 Now Done.
623 int seconds = params->seconds;
624
625 if (seconds < -1) {
626 return RespondNow(
627 Error("Invalid argument: *.", base::IntToString(seconds)));
628 }
629
630 RuntimeAPI::GetFactoryInstance()
631 ->Get(browser_context())
632 ->RestartDeviceOnWatchdogTimeout(
633 extension(), seconds,
634 base::Bind(&RuntimeRestartOnWatchdogFunction::OnWatchdogTimeout,
635 this));
636
637 return RespondLater();
638 }
639
640 void RuntimeRestartOnWatchdogFunction::OnWatchdogTimeout(
641 bool success,
642 const std::string& message) {
643 if (!success)
644 WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_ERROR, message);
645
646 Respond(ArgumentList(
xiyuan 2016/05/13 17:56:15 I thought we would invoke the callback when the wa
afakhry 2016/05/14 01:27:35 Done. I made sure any previously scheduled callbac
647 api::runtime::RestartOnWatchdog::Results::Create(success, message)));
648 }
649
554 ExtensionFunction::ResponseAction RuntimeGetPlatformInfoFunction::Run() { 650 ExtensionFunction::ResponseAction RuntimeGetPlatformInfoFunction::Run() {
555 runtime::PlatformInfo info; 651 runtime::PlatformInfo info;
556 if (!RuntimeAPI::GetFactoryInstance() 652 if (!RuntimeAPI::GetFactoryInstance()
557 ->Get(browser_context()) 653 ->Get(browser_context())
558 ->GetPlatformInfo(&info)) { 654 ->GetPlatformInfo(&info)) {
559 return RespondNow(Error(kPlatformInfoUnavailable)); 655 return RespondNow(Error(kPlatformInfoUnavailable));
560 } 656 }
561 return RespondNow( 657 return RespondNow(
562 ArgumentList(runtime::GetPlatformInfo::Results::Create(info))); 658 ArgumentList(runtime::GetPlatformInfo::Results::Create(info)));
563 } 659 }
(...skipping 13 matching lines...) Expand all
577 content::ChildProcessSecurityPolicy* policy = 673 content::ChildProcessSecurityPolicy* policy =
578 content::ChildProcessSecurityPolicy::GetInstance(); 674 content::ChildProcessSecurityPolicy::GetInstance();
579 policy->GrantReadFileSystem(renderer_id, filesystem_id); 675 policy->GrantReadFileSystem(renderer_id, filesystem_id);
580 base::DictionaryValue* dict = new base::DictionaryValue(); 676 base::DictionaryValue* dict = new base::DictionaryValue();
581 dict->SetString("fileSystemId", filesystem_id); 677 dict->SetString("fileSystemId", filesystem_id);
582 dict->SetString("baseName", relative_path); 678 dict->SetString("baseName", relative_path);
583 return RespondNow(OneArgument(dict)); 679 return RespondNow(OneArgument(dict));
584 } 680 }
585 681
586 } // namespace extensions 682 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698