OLD | NEW |
| (Empty) |
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/ui/webui/options/chromeos/about_page_handler.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/basictypes.h" | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/command_line.h" | |
13 #include "base/i18n/time_formatting.h" | |
14 #include "base/string16.h" | |
15 #include "base/string_number_conversions.h" | |
16 #include "base/time.h" | |
17 #include "base/utf_string_conversions.h" | |
18 #include "base/values.h" | |
19 #include "chrome/browser/browser_process.h" | |
20 #include "chrome/browser/chromeos/cros_settings.h" | |
21 #include "chrome/browser/chromeos/dbus/dbus_thread_manager.h" | |
22 #include "chrome/browser/chromeos/dbus/power_manager_client.h" | |
23 #include "chrome/browser/chromeos/dbus/update_engine_client.h" | |
24 #include "chrome/browser/chromeos/login/user_manager.h" | |
25 #include "chrome/browser/chromeos/login/wizard_controller.h" | |
26 #include "chrome/browser/google/google_util.h" | |
27 #include "chrome/browser/policy/browser_policy_connector.h" | |
28 #include "chrome/common/chrome_version_info.h" | |
29 #include "chrome/common/url_constants.h" | |
30 #include "content/public/browser/web_ui.h" | |
31 #include "content/public/common/content_client.h" | |
32 #include "googleurl/src/gurl.h" | |
33 #include "grit/chromium_strings.h" | |
34 #include "grit/generated_resources.h" | |
35 #include "grit/locale_settings.h" | |
36 #include "grit/theme_resources.h" | |
37 #include "ui/base/l10n/l10n_util.h" | |
38 #include "ui/base/resource/resource_bundle.h" | |
39 #include "v8/include/v8.h" | |
40 #include "webkit/glue/user_agent.h" | |
41 #include "webkit/glue/webkit_glue.h" | |
42 #include "webkit/glue/user_agent.h" | |
43 | |
44 namespace { | |
45 | |
46 // These are used as placeholder text around the links in the text in the | |
47 // license. | |
48 const char kBeginLink[] = "BEGIN_LINK"; | |
49 const char kEndLink[] = "END_LINK"; | |
50 const char kBeginLinkChr[] = "BEGIN_LINK_CHR"; | |
51 const char kBeginLinkOss[] = "BEGIN_LINK_OSS"; | |
52 const char kEndLinkChr[] = "END_LINK_CHR"; | |
53 const char kEndLinkOss[] = "END_LINK_OSS"; | |
54 const char kBeginLinkCrosOss[] = "BEGIN_LINK_CROS_OSS"; | |
55 const char kEndLinkCrosOss[] = "END_LINK_CROS_OSS"; | |
56 | |
57 // Returns a substring [start, end) from |text|. | |
58 std::string StringSubRange(const std::string& text, size_t start, | |
59 size_t end) { | |
60 DCHECK(end > start); | |
61 return text.substr(start, end - start); | |
62 } | |
63 | |
64 bool CanChangeReleaseChannel() { | |
65 // On non managed machines we have local owner who is the only one to change | |
66 // anything. | |
67 if (chromeos::UserManager::Get()->IsCurrentUserOwner()) | |
68 return true; | |
69 // On a managed machine we delegate this setting to the users of the same | |
70 // domain only if the policy value is "domain". | |
71 if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) { | |
72 bool value = false; | |
73 if (!chromeos::CrosSettings::Get()->GetBoolean( | |
74 chromeos::kReleaseChannelDelegated, &value) || !value) | |
75 return false; | |
76 // Get the currently logged in user and strip the domain part only. | |
77 std::string domain = ""; | |
78 std::string user = chromeos::UserManager::Get()->GetLoggedInUser().email(); | |
79 size_t at_pos = user.find('@'); | |
80 if (at_pos != std::string::npos && at_pos + 1 < user.length()) | |
81 domain = user.substr(user.find('@') + 1); | |
82 return domain == g_browser_process->browser_policy_connector()-> | |
83 GetEnterpriseDomain(); | |
84 } | |
85 return false; | |
86 } | |
87 | |
88 } // namespace | |
89 | |
90 namespace chromeos { | |
91 | |
92 class AboutPageHandler::UpdateObserver | |
93 : public UpdateEngineClient::Observer { | |
94 public: | |
95 explicit UpdateObserver(AboutPageHandler* handler) : page_handler_(handler) {} | |
96 virtual ~UpdateObserver() {} | |
97 | |
98 AboutPageHandler* page_handler() const { return page_handler_; } | |
99 | |
100 private: | |
101 virtual void UpdateStatusChanged( | |
102 const UpdateEngineClient::Status& status) OVERRIDE { | |
103 page_handler_->UpdateStatus(status); | |
104 } | |
105 | |
106 AboutPageHandler* page_handler_; | |
107 | |
108 DISALLOW_COPY_AND_ASSIGN(UpdateObserver); | |
109 }; | |
110 | |
111 AboutPageHandler::AboutPageHandler() | |
112 : progress_(-1), | |
113 sticky_(false), | |
114 started_(false) | |
115 {} | |
116 | |
117 AboutPageHandler::~AboutPageHandler() { | |
118 if (update_observer_.get()) { | |
119 DBusThreadManager::Get()->GetUpdateEngineClient()-> | |
120 RemoveObserver(update_observer_.get()); | |
121 } | |
122 } | |
123 | |
124 void AboutPageHandler::GetLocalizedValues(DictionaryValue* localized_strings) { | |
125 DCHECK(localized_strings); | |
126 | |
127 static OptionsStringResource resources[] = { | |
128 { "firmware", IDS_ABOUT_PAGE_FIRMWARE }, | |
129 { "product", IDS_PRODUCT_OS_NAME }, | |
130 { "os", IDS_PRODUCT_OS_NAME }, | |
131 { "platform", IDS_PLATFORM_LABEL }, | |
132 { "loading", IDS_ABOUT_PAGE_LOADING }, | |
133 { "check_now", IDS_ABOUT_PAGE_CHECK_NOW }, | |
134 { "update_status", IDS_UPGRADE_CHECK_STARTED }, | |
135 { "restart_now", IDS_RELAUNCH_AND_UPDATE }, | |
136 { "browser", IDS_PRODUCT_NAME }, | |
137 { "more_info", IDS_ABOUT_PAGE_MORE_INFO }, | |
138 { "copyright", IDS_ABOUT_VERSION_COPYRIGHT }, | |
139 { "channel", IDS_ABOUT_PAGE_CHANNEL }, | |
140 { "stable", IDS_ABOUT_PAGE_CHANNEL_STABLE }, | |
141 { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA }, | |
142 { "dev", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT }, | |
143 { "canary", IDS_ABOUT_PAGE_CHANNEL_CANARY }, | |
144 { "channel_warning_header", IDS_ABOUT_PAGE_CHANNEL_WARNING_HEADER }, | |
145 { "channel_warning_text", IDS_ABOUT_PAGE_CHANNEL_WARNING_TEXT }, | |
146 { "user_agent", IDS_ABOUT_VERSION_USER_AGENT }, | |
147 { "command_line", IDS_ABOUT_VERSION_COMMAND_LINE }, | |
148 }; | |
149 | |
150 RegisterStrings(localized_strings, resources, arraysize(resources)); | |
151 RegisterTitle(localized_strings, "aboutPage", IDS_ABOUT_TAB_TITLE); | |
152 | |
153 // browser version | |
154 | |
155 chrome::VersionInfo version_info; | |
156 DCHECK(version_info.is_valid()); | |
157 | |
158 std::string browser_version = version_info.Version(); | |
159 std::string version_modifier = | |
160 chrome::VersionInfo::GetVersionStringModifier(); | |
161 if (!version_modifier.empty()) | |
162 browser_version += " " + version_modifier; | |
163 | |
164 #if !defined(GOOGLE_CHROME_BUILD) | |
165 browser_version += " ("; | |
166 browser_version += version_info.LastChange(); | |
167 browser_version += ")"; | |
168 #endif | |
169 | |
170 localized_strings->SetString("browser_version", browser_version); | |
171 | |
172 // license | |
173 | |
174 std::string text = l10n_util::GetStringUTF8(IDS_ABOUT_OLD_VERSION_LICENSE); | |
175 | |
176 bool chromium_url_appears_first = | |
177 text.find(kBeginLinkChr) < text.find(kBeginLinkOss); | |
178 | |
179 size_t link1 = text.find(kBeginLink); | |
180 DCHECK(link1 != std::string::npos); | |
181 size_t link1_end = text.find(kEndLink, link1); | |
182 DCHECK(link1_end != std::string::npos); | |
183 size_t link2 = text.find(kBeginLink, link1_end); | |
184 DCHECK(link2 != std::string::npos); | |
185 size_t link2_end = text.find(kEndLink, link2); | |
186 DCHECK(link2_end != std::string::npos); | |
187 | |
188 localized_strings->SetString("license_content_0", text.substr(0, link1)); | |
189 localized_strings->SetString("license_content_1", | |
190 StringSubRange(text, link1_end + strlen(kEndLinkOss), link2)); | |
191 localized_strings->SetString("license_content_2", | |
192 text.substr(link2_end + strlen(kEndLinkOss))); | |
193 | |
194 // The Chromium link within the main text of the dialog. | |
195 localized_strings->SetString(chromium_url_appears_first ? | |
196 "license_link_content_0" : "license_link_content_1", | |
197 StringSubRange(text, | |
198 text.find(kBeginLinkChr) + strlen(kBeginLinkChr), | |
199 text.find(kEndLinkChr))); | |
200 GURL url = google_util::AppendGoogleLocaleParam( | |
201 GURL(chrome::kChromiumProjectURL)); | |
202 localized_strings->SetString(chromium_url_appears_first ? | |
203 "license_link_0" : "license_link_1", url.spec()); | |
204 | |
205 // The Open Source link within the main text of the dialog. | |
206 localized_strings->SetString(chromium_url_appears_first ? | |
207 "license_link_content_1" : "license_link_content_0", | |
208 StringSubRange(text, | |
209 text.find(kBeginLinkOss) + strlen(kBeginLinkOss), | |
210 text.find(kEndLinkOss))); | |
211 localized_strings->SetString(chromium_url_appears_first ? | |
212 "license_link_1" : "license_link_0", chrome::kChromeUICreditsURL); | |
213 | |
214 std::string cros_text = | |
215 l10n_util::GetStringUTF8(IDS_ABOUT_CROS_VERSION_LICENSE); | |
216 | |
217 size_t cros_link = cros_text.find(kBeginLinkCrosOss); | |
218 DCHECK(cros_link != std::string::npos); | |
219 size_t cros_link_end = cros_text.find(kEndLinkCrosOss, cros_link); | |
220 DCHECK(cros_link_end != std::string::npos); | |
221 | |
222 localized_strings->SetString("cros_license_content_0", | |
223 cros_text.substr(0, cros_link)); | |
224 localized_strings->SetString("cros_license_content_1", | |
225 cros_text.substr(cros_link_end + strlen(kEndLinkCrosOss))); | |
226 localized_strings->SetString("cros_license_link_content_0", | |
227 StringSubRange(cros_text, cros_link + strlen(kBeginLinkCrosOss), | |
228 cros_link_end)); | |
229 localized_strings->SetString("cros_license_link_0", | |
230 chrome::kChromeUIOSCreditsURL); | |
231 | |
232 // webkit | |
233 | |
234 localized_strings->SetString("webkit_version", | |
235 webkit_glue::GetWebKitVersion()); | |
236 | |
237 // javascript | |
238 | |
239 localized_strings->SetString("js_engine", "V8"); | |
240 localized_strings->SetString("js_engine_version", v8::V8::GetVersion()); | |
241 | |
242 // user agent | |
243 | |
244 localized_strings->SetString("user_agent_info", | |
245 content::GetUserAgent(GURL())); | |
246 | |
247 // command line | |
248 | |
249 #if defined(OS_WIN) | |
250 localized_strings->SetString("command_line_info", | |
251 WideToUTF16(CommandLine::ForCurrentProcess()->GetCommandLineString())); | |
252 #elif defined(OS_POSIX) | |
253 // TODO(viettrungluu): something horrible might happen if there are non-UTF-8 | |
254 // arguments (since |SetString()| requires Unicode). | |
255 std::string command_line = ""; | |
256 typedef std::vector<std::string> ArgvList; | |
257 const ArgvList& argv = CommandLine::ForCurrentProcess()->argv(); | |
258 for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++) | |
259 command_line += " " + *iter; | |
260 localized_strings->SetString("command_line_info", command_line); | |
261 #endif | |
262 } | |
263 | |
264 void AboutPageHandler::RegisterMessages() { | |
265 web_ui()->RegisterMessageCallback("PageReady", | |
266 base::Bind(&AboutPageHandler::PageReady, base::Unretained(this))); | |
267 web_ui()->RegisterMessageCallback("SetReleaseTrack", | |
268 base::Bind(&AboutPageHandler::SetReleaseTrack, base::Unretained(this))); | |
269 | |
270 web_ui()->RegisterMessageCallback("CheckNow", | |
271 base::Bind(&AboutPageHandler::CheckNow, base::Unretained(this))); | |
272 web_ui()->RegisterMessageCallback("RestartNow", | |
273 base::Bind(&AboutPageHandler::RestartNow, base::Unretained(this))); | |
274 } | |
275 | |
276 void AboutPageHandler::PageReady(const ListValue* args) { | |
277 // Version information is loaded from a callback | |
278 loader_.GetVersion(&consumer_, | |
279 base::Bind(&AboutPageHandler::OnOSVersion, | |
280 base::Unretained(this)), | |
281 VersionLoader::VERSION_FULL); | |
282 loader_.GetFirmware(&consumer_, | |
283 base::Bind(&AboutPageHandler::OnOSFirmware, | |
284 base::Unretained(this))); | |
285 | |
286 scoped_ptr<base::Value> can_change_channel_value( | |
287 base::Value::CreateBooleanValue(CanChangeReleaseChannel())); | |
288 web_ui()->CallJavascriptFunction( | |
289 "AboutPage.updateEnableReleaseChannelCallback", | |
290 *can_change_channel_value); | |
291 | |
292 UpdateEngineClient* update_engine_client = | |
293 DBusThreadManager::Get()->GetUpdateEngineClient(); | |
294 | |
295 update_observer_.reset(new UpdateObserver(this)); | |
296 update_engine_client->AddObserver(update_observer_.get()); | |
297 | |
298 // Update the WebUI page with the current status. See comments below. | |
299 UpdateStatus(update_engine_client->GetLastStatus()); | |
300 | |
301 // Initiate update check. UpdateStatus() below will be called when we | |
302 // get update status via update_observer_. If the update has been | |
303 // already complete, update_observer_ won't receive a notification. | |
304 // This is why we manually update the WebUI page above. | |
305 CheckNow(NULL); | |
306 | |
307 // Request the channel information. Use the observer to track the about | |
308 // page handler and ensure it does not get deleted before the callback. | |
309 update_engine_client->GetReleaseTrack( | |
310 base::Bind(UpdateSelectedChannel, update_observer_.get())); | |
311 } | |
312 | |
313 void AboutPageHandler::SetReleaseTrack(const ListValue* args) { | |
314 if (!CanChangeReleaseChannel()) { | |
315 LOG(WARNING) << "Non-owner tried to change release track."; | |
316 return; | |
317 } | |
318 const std::string channel = UTF16ToUTF8(ExtractStringValue(args)); | |
319 DBusThreadManager::Get()->GetUpdateEngineClient()->SetReleaseTrack(channel); | |
320 // For local owner set the field in the policy blob too. | |
321 if (UserManager::Get()->IsCurrentUserOwner()) | |
322 CrosSettings::Get()->SetString(kReleaseChannel, channel); | |
323 } | |
324 | |
325 void AboutPageHandler::CheckNow(const ListValue* args) { | |
326 // Make sure that libcros is loaded and OOBE is complete. | |
327 if (!WizardController::default_controller() || | |
328 WizardController::IsDeviceRegistered()) { | |
329 DBusThreadManager::Get()->GetUpdateEngineClient()-> | |
330 RequestUpdateCheck(UpdateEngineClient::EmptyUpdateCheckCallback()); | |
331 } | |
332 } | |
333 | |
334 void AboutPageHandler::RestartNow(const ListValue* args) { | |
335 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); | |
336 } | |
337 | |
338 void AboutPageHandler::UpdateStatus( | |
339 const UpdateEngineClient::Status& status) { | |
340 string16 message; | |
341 std::string image = "up-to-date"; | |
342 bool enabled = false; | |
343 | |
344 switch (status.status) { | |
345 case UpdateEngineClient::UPDATE_STATUS_IDLE: | |
346 if (!sticky_) { | |
347 message = l10n_util::GetStringUTF16(IDS_UPGRADE_UP_TO_DATE); | |
348 enabled = true; | |
349 } | |
350 break; | |
351 case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE: | |
352 message = l10n_util::GetStringUTF16(IDS_UPGRADE_CHECK_STARTED); | |
353 sticky_ = false; | |
354 break; | |
355 case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE: | |
356 message = l10n_util::GetStringUTF16(IDS_UPDATE_AVAILABLE); | |
357 started_ = true; | |
358 break; | |
359 case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING: | |
360 { | |
361 int progress = static_cast<int>(status.download_progress * 100.0); | |
362 if (progress != progress_) { | |
363 progress_ = progress; | |
364 message = l10n_util::GetStringFUTF16Int(IDS_UPDATE_DOWNLOADING, | |
365 progress_); | |
366 } | |
367 started_ = true; | |
368 } | |
369 break; | |
370 case UpdateEngineClient::UPDATE_STATUS_VERIFYING: | |
371 message = l10n_util::GetStringUTF16(IDS_UPDATE_VERIFYING); | |
372 started_ = true; | |
373 break; | |
374 case UpdateEngineClient::UPDATE_STATUS_FINALIZING: | |
375 message = l10n_util::GetStringUTF16(IDS_UPDATE_FINALIZING); | |
376 started_ = true; | |
377 break; | |
378 case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT: | |
379 message = l10n_util::GetStringUTF16(IDS_UPDATE_COMPLETED); | |
380 image = "available"; | |
381 sticky_ = true; | |
382 break; | |
383 default: | |
384 // case UpdateEngineClient::UPDATE_STATUS_ERROR: | |
385 // case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT: | |
386 | |
387 // The error is only displayed if we were able to determine an | |
388 // update was available. | |
389 if (started_) { | |
390 message = l10n_util::GetStringUTF16(IDS_UPDATE_ERROR); | |
391 image = "fail"; | |
392 enabled = true; | |
393 sticky_ = true; | |
394 started_ = false; | |
395 } | |
396 break; | |
397 } | |
398 if (message.size()) { | |
399 scoped_ptr<Value> update_message(Value::CreateStringValue(message)); | |
400 // "Checking for update..." needs to be shown for a while, so users | |
401 // can read it, hence insert delay for this. | |
402 scoped_ptr<Value> insert_delay(Value::CreateBooleanValue( | |
403 status.status == | |
404 UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE)); | |
405 web_ui()->CallJavascriptFunction("AboutPage.updateStatusCallback", | |
406 *update_message, *insert_delay); | |
407 | |
408 scoped_ptr<Value> enabled_value(Value::CreateBooleanValue(enabled)); | |
409 web_ui()->CallJavascriptFunction("AboutPage.updateEnableCallback", | |
410 *enabled_value); | |
411 | |
412 scoped_ptr<Value> image_string(Value::CreateStringValue(image)); | |
413 web_ui()->CallJavascriptFunction("AboutPage.setUpdateImage", | |
414 *image_string); | |
415 } | |
416 // We'll change the "Check For Update" button to "Restart" button. | |
417 if (status.status == UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { | |
418 web_ui()->CallJavascriptFunction("AboutPage.changeToRestartButton"); | |
419 } | |
420 } | |
421 | |
422 void AboutPageHandler::OnOSVersion(VersionLoader::Handle handle, | |
423 std::string version) { | |
424 if (version.size()) { | |
425 scoped_ptr<Value> version_string(Value::CreateStringValue(version)); | |
426 web_ui()->CallJavascriptFunction("AboutPage.updateOSVersionCallback", | |
427 *version_string); | |
428 } | |
429 } | |
430 | |
431 void AboutPageHandler::OnOSFirmware(VersionLoader::Handle handle, | |
432 std::string firmware) { | |
433 if (firmware.size()) { | |
434 scoped_ptr<Value> firmware_string(Value::CreateStringValue(firmware)); | |
435 web_ui()->CallJavascriptFunction("AboutPage.updateOSFirmwareCallback", | |
436 *firmware_string); | |
437 } | |
438 } | |
439 | |
440 // Callback from UpdateEngine with channel information. | |
441 // static | |
442 void AboutPageHandler::UpdateSelectedChannel(UpdateObserver* observer, | |
443 const std::string& channel) { | |
444 if (DBusThreadManager::Get()->GetUpdateEngineClient() | |
445 ->HasObserver(observer)) { | |
446 // If UpdateEngineClient still has the observer, then the page handler | |
447 // is valid. | |
448 AboutPageHandler* handler = observer->page_handler(); | |
449 scoped_ptr<Value> channel_string(Value::CreateStringValue(channel)); | |
450 handler->web_ui()->CallJavascriptFunction( | |
451 "AboutPage.updateSelectedOptionCallback", *channel_string); | |
452 } | |
453 } | |
454 | |
455 } // namespace chromeos | |
OLD | NEW |