1// Copyright (c) 2012 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/system_private/system_private_api.h"
6
7#include "base/prefs/pref_service.h"
8#include "base/values.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/extensions/event_router_forwarder.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/common/extensions/api/system_private.h"
13#include "chrome/common/pref_names.h"
14#include "google_apis/google_api_keys.h"
15
16#if defined(OS_CHROMEOS)
17#include "chromeos/dbus/dbus_thread_manager.h"
18#include "chromeos/dbus/update_engine_client.h"
19#else
20#include "chrome/browser/upgrade_detector.h"
21#endif
22
23namespace {
24
25// Maps prefs::kIncognitoModeAvailability values (0 = enabled, ...)
26// to strings exposed to extensions.
27const char* kIncognitoModeAvailabilityStrings[] = {
28  "enabled",
29  "disabled",
30  "forced"
31};
32
33// Property keys.
34const char kBrightnessKey[] = "brightness";
35const char kDownloadProgressKey[] = "downloadProgress";
36const char kIsVolumeMutedKey[] = "isVolumeMuted";
37const char kStateKey[] = "state";
38const char kUserInitiatedKey[] = "userInitiated";
39const char kVolumeKey[] = "volume";
40
41// System update states.
42const char kNotAvailableState[] = "NotAvailable";
43const char kNeedRestartState[] = "NeedRestart";
44
45#if defined(OS_CHROMEOS)
46const char kUpdatingState[] = "Updating";
47#endif  // defined(OS_CHROMEOS)
48
49// Dispatches an extension event with |argument|
50void DispatchEvent(const std::string& event_name, base::Value* argument) {
51  scoped_ptr<base::ListValue> list_args(new base::ListValue());
52  if (argument) {
53    list_args->Append(argument);
54  }
55  g_browser_process->extension_event_router_forwarder()->
56      BroadcastEventToRenderers(event_name, list_args.Pass(), GURL());
57}
58
59}  // namespace
60
61namespace extensions {
62
63namespace system_private = api::system_private;
64
65bool SystemPrivateGetIncognitoModeAvailabilityFunction::RunSync() {
66  PrefService* prefs = GetProfile()->GetPrefs();
67  int value = prefs->GetInteger(prefs::kIncognitoModeAvailability);
68  EXTENSION_FUNCTION_VALIDATE(
69      value >= 0 &&
70      value < static_cast<int>(arraysize(kIncognitoModeAvailabilityStrings)));
71  SetResult(new base::StringValue(kIncognitoModeAvailabilityStrings[value]));
72  return true;
73}
74
75bool SystemPrivateGetUpdateStatusFunction::RunSync() {
76  std::string state;
77  double download_progress = 0;
78#if defined(OS_CHROMEOS)
79  // With UpdateEngineClient, we can provide more detailed information about
80  // system updates on ChromeOS.
81  const chromeos::UpdateEngineClient::Status status =
82      chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
83      GetLastStatus();
84  // |download_progress| is set to 1 after download finishes
85  // (i.e. verify, finalize and need-reboot phase) to indicate the progress
86  // even though |status.download_progress| is 0 in these phases.
87  switch (status.status) {
88    case chromeos::UpdateEngineClient::UPDATE_STATUS_ERROR:
89      state = kNotAvailableState;
90      break;
91    case chromeos::UpdateEngineClient::UPDATE_STATUS_IDLE:
92      state = kNotAvailableState;
93      break;
94    case chromeos::UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE:
95      state = kNotAvailableState;
96      break;
97    case chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE:
98      state = kUpdatingState;
99      break;
100    case chromeos::UpdateEngineClient::UPDATE_STATUS_DOWNLOADING:
101      state = kUpdatingState;
102      download_progress = status.download_progress;
103      break;
104    case chromeos::UpdateEngineClient::UPDATE_STATUS_VERIFYING:
105      state = kUpdatingState;
106      download_progress = 1;
107      break;
108    case chromeos::UpdateEngineClient::UPDATE_STATUS_FINALIZING:
109      state = kUpdatingState;
110      download_progress = 1;
111      break;
112    case chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT:
113      state = kNeedRestartState;
114      download_progress = 1;
115      break;
116    case chromeos::UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT:
117    case chromeos::UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK:
118      state = kNotAvailableState;
119      break;
120  }
121#else
122  if (UpgradeDetector::GetInstance()->notify_upgrade()) {
123    state = kNeedRestartState;
124    download_progress = 1;
125  } else {
126    state = kNotAvailableState;
127  }
128#endif
129  base::DictionaryValue* dict = new base::DictionaryValue();
130  dict->SetString(kStateKey, state);
131  dict->SetDouble(kDownloadProgressKey, download_progress);
132  SetResult(dict);
133
134  return true;
135}
136
137bool SystemPrivateGetApiKeyFunction::RunSync() {
138  SetResult(new base::StringValue(google_apis::GetAPIKey()));
139  return true;
140}
141
142void DispatchVolumeChangedEvent(double volume, bool is_volume_muted) {
143  base::DictionaryValue* dict = new base::DictionaryValue();
144  dict->SetDouble(kVolumeKey, volume);
145  dict->SetBoolean(kIsVolumeMutedKey, is_volume_muted);
146  DispatchEvent(system_private::OnVolumeChanged::kEventName, dict);
147}
148
149void DispatchBrightnessChangedEvent(int brightness, bool user_initiated) {
150  base::DictionaryValue* dict = new base::DictionaryValue();
151  dict->SetInteger(kBrightnessKey, brightness);
152  dict->SetBoolean(kUserInitiatedKey, user_initiated);
153  DispatchEvent(system_private::OnBrightnessChanged::kEventName, dict);
154}
155
156void DispatchScreenUnlockedEvent() {
157  DispatchEvent(system_private::OnScreenUnlocked::kEventName, NULL);
158}
159
160void DispatchWokeUpEvent() {
161  DispatchEvent(system_private::OnWokeUp::kEventName, NULL);
162}
163
164}  // namespace extensions
165