1// Copyright 2013 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/components_ui.h" 6 7#include <algorithm> 8#include <string> 9#include <vector> 10 11#include "base/values.h" 12#include "chrome/browser/browser_process.h" 13#include "chrome/browser/ui/browser.h" 14#include "chrome/browser/ui/browser_window.h" 15#include "chrome/common/chrome_paths.h" 16#include "chrome/common/url_constants.h" 17#include "chrome/grit/generated_resources.h" 18#include "components/component_updater/component_updater_service.h" 19#include "components/component_updater/crx_update_item.h" 20#include "content/public/browser/web_ui.h" 21#include "content/public/browser/web_ui_data_source.h" 22#include "content/public/browser/web_ui_message_handler.h" 23#include "grit/browser_resources.h" 24#include "grit/theme_resources.h" 25#include "ui/base/l10n/l10n_util.h" 26#include "ui/base/resource/resource_bundle.h" 27 28#if defined(OS_CHROMEOS) 29#include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h" 30#endif 31 32using content::WebUIMessageHandler; 33 34namespace { 35 36content::WebUIDataSource* CreateComponentsUIHTMLSource(Profile* profile) { 37 content::WebUIDataSource* source = 38 content::WebUIDataSource::Create(chrome::kChromeUIComponentsHost); 39 source->SetUseJsonJSFormatV2(); 40 41 source->AddLocalizedString("componentsTitle", IDS_COMPONENTS_TITLE); 42 source->AddLocalizedString("componentsNoneInstalled", 43 IDS_COMPONENTS_NONE_INSTALLED); 44 source->AddLocalizedString("componentVersion", IDS_COMPONENTS_VERSION); 45 source->AddLocalizedString("checkUpdate", IDS_COMPONENTS_CHECK_FOR_UPDATE); 46 source->AddLocalizedString("noComponents", IDS_COMPONENTS_NO_COMPONENTS); 47 source->AddLocalizedString("statusLabel", IDS_COMPONENTS_STATUS_LABEL); 48 source->AddLocalizedString("checkingLabel", IDS_COMPONENTS_CHECKING_LABEL); 49 50 source->SetJsonPath("strings.js"); 51 source->AddResourcePath("components.js", IDR_COMPONENTS_JS); 52 source->SetDefaultResource(IDR_COMPONENTS_HTML); 53#if defined(OS_CHROMEOS) 54 chromeos::AddAccountUITweaksLocalizedValues(source, profile); 55#endif 56 return source; 57} 58 59//////////////////////////////////////////////////////////////////////////////// 60// 61// ComponentsDOMHandler 62// 63//////////////////////////////////////////////////////////////////////////////// 64 65// The handler for Javascript messages for the chrome://components/ page. 66class ComponentsDOMHandler : public WebUIMessageHandler { 67 public: 68 ComponentsDOMHandler(); 69 virtual ~ComponentsDOMHandler() {} 70 71 // WebUIMessageHandler implementation. 72 virtual void RegisterMessages() OVERRIDE; 73 74 // Callback for the "requestComponentsData" message. 75 void HandleRequestComponentsData(const base::ListValue* args); 76 77 // Callback for the "checkUpdate" message. 78 void HandleCheckUpdate(const base::ListValue* args); 79 80 private: 81 content::NotificationRegistrar registrar_; 82 83 DISALLOW_COPY_AND_ASSIGN(ComponentsDOMHandler); 84}; 85 86ComponentsDOMHandler::ComponentsDOMHandler() { 87} 88 89void ComponentsDOMHandler::RegisterMessages() { 90 web_ui()->RegisterMessageCallback( 91 "requestComponentsData", 92 base::Bind(&ComponentsDOMHandler::HandleRequestComponentsData, 93 base::Unretained(this))); 94 95 web_ui()->RegisterMessageCallback( 96 "checkUpdate", 97 base::Bind(&ComponentsDOMHandler::HandleCheckUpdate, 98 base::Unretained(this))); 99} 100 101void ComponentsDOMHandler::HandleRequestComponentsData( 102 const base::ListValue* args) { 103 base::ListValue* list = ComponentsUI::LoadComponents(); 104 base::DictionaryValue result; 105 result.Set("components", list); 106 web_ui()->CallJavascriptFunction("returnComponentsData", result); 107} 108 109// This function is called when user presses button from html UI. 110// TODO(shrikant): We need to make this button available based on current 111// state e.g. If component state is currently updating then we need to disable 112// button. (https://code.google.com/p/chromium/issues/detail?id=272540) 113void ComponentsDOMHandler::HandleCheckUpdate(const base::ListValue* args) { 114 if (args->GetSize() != 1) { 115 NOTREACHED(); 116 return; 117 } 118 119 std::string component_id; 120 if (!args->GetString(0, &component_id)) { 121 NOTREACHED(); 122 return; 123 } 124 125 ComponentsUI::OnDemandUpdate(component_id); 126} 127 128} // namespace 129 130/////////////////////////////////////////////////////////////////////////////// 131// 132// ComponentsUI 133// 134/////////////////////////////////////////////////////////////////////////////// 135 136ComponentsUI::ComponentsUI(content::WebUI* web_ui) : WebUIController(web_ui) { 137 web_ui->AddMessageHandler(new ComponentsDOMHandler()); 138 139 // Set up the chrome://components/ source. 140 Profile* profile = Profile::FromWebUI(web_ui); 141 content::WebUIDataSource::Add(profile, CreateComponentsUIHTMLSource(profile)); 142 component_updater::ComponentUpdateService* cus = 143 g_browser_process->component_updater(); 144 cus->AddObserver(this); 145} 146 147ComponentsUI::~ComponentsUI() { 148 component_updater::ComponentUpdateService* cus = 149 g_browser_process->component_updater(); 150 if (cus) 151 cus->RemoveObserver(this); 152} 153 154// static 155void ComponentsUI::OnDemandUpdate(const std::string& component_id) { 156 component_updater::ComponentUpdateService* cus = 157 g_browser_process->component_updater(); 158 cus->GetOnDemandUpdater().OnDemandUpdate(component_id); 159} 160 161// static 162base::ListValue* ComponentsUI::LoadComponents() { 163 component_updater::ComponentUpdateService* cus = 164 g_browser_process->component_updater(); 165 std::vector<std::string> component_ids; 166 component_ids = cus->GetComponentIDs(); 167 168 // Construct DictionaryValues to return to UI. 169 base::ListValue* component_list = new base::ListValue(); 170 for (size_t j = 0; j < component_ids.size(); ++j) { 171 component_updater::CrxUpdateItem item; 172 if (cus->GetComponentDetails(component_ids[j], &item)) { 173 base::DictionaryValue* component_entry = new base::DictionaryValue(); 174 component_entry->SetString("id", component_ids[j]); 175 component_entry->SetString("name", item.component.name); 176 component_entry->SetString("version", item.component.version.GetString()); 177 component_entry->SetString("status", ServiceStatusToString(item.status)); 178 component_list->Append(component_entry); 179 } 180 } 181 182 return component_list; 183} 184 185// static 186base::RefCountedMemory* ComponentsUI::GetFaviconResourceBytes( 187 ui::ScaleFactor scale_factor) { 188 return ResourceBundle::GetSharedInstance(). 189 LoadDataResourceBytesForScale(IDR_PLUGINS_FAVICON, scale_factor); 190} 191 192base::string16 ComponentsUI::ComponentEventToString(Events event) { 193 switch (event) { 194 case COMPONENT_UPDATER_STARTED: 195 return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_STARTED); 196 case COMPONENT_UPDATER_SLEEPING: 197 return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_SLEEPING); 198 case COMPONENT_UPDATE_FOUND: 199 return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_FOUND); 200 case COMPONENT_UPDATE_READY: 201 return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_READY); 202 case COMPONENT_UPDATED: 203 return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_UPDATED); 204 case COMPONENT_NOT_UPDATED: 205 return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_NOTUPDATED); 206 case COMPONENT_UPDATE_DOWNLOADING: 207 return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_DOWNLOADING); 208 } 209 return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN); 210} 211 212base::string16 ComponentsUI::ServiceStatusToString( 213 component_updater::CrxUpdateItem::Status status) { 214 switch (status) { 215 case component_updater::CrxUpdateItem::kNew: 216 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_NEW); 217 case component_updater::CrxUpdateItem::kChecking: 218 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_CHECKING); 219 case component_updater::CrxUpdateItem::kCanUpdate: 220 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE); 221 case component_updater::CrxUpdateItem::kDownloadingDiff: 222 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL_DIFF); 223 case component_updater::CrxUpdateItem::kDownloading: 224 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL); 225 case component_updater::CrxUpdateItem::kUpdatingDiff: 226 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDT_DIFF); 227 case component_updater::CrxUpdateItem::kUpdating: 228 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATING); 229 case component_updater::CrxUpdateItem::kUpdated: 230 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATED); 231 case component_updater::CrxUpdateItem::kUpToDate: 232 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPTODATE); 233 case component_updater::CrxUpdateItem::kNoUpdate: 234 return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_NOUPDATE); 235 case component_updater::CrxUpdateItem::kLastStatus: 236 return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN); 237 } 238 return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN); 239} 240 241void ComponentsUI::OnEvent(Events event, const std::string& id) { 242 base::DictionaryValue parameters; 243 parameters.SetString("event", ComponentEventToString(event)); 244 if (!id.empty()) { 245 using component_updater::ComponentUpdateService; 246 if (event == ComponentUpdateService::Observer::COMPONENT_UPDATED) { 247 ComponentUpdateService* cus = g_browser_process->component_updater(); 248 component_updater::CrxUpdateItem item; 249 if (cus->GetComponentDetails(id, &item)) 250 parameters.SetString("version", item.component.version.GetString()); 251 } 252 parameters.SetString("id", id); 253 } 254 web_ui()->CallJavascriptFunction("onComponentEvent", parameters); 255} 256