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 32 using content::WebUIMessageHandler; 33 34 namespace { 35 36 content::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. 66 class 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 86 ComponentsDOMHandler::ComponentsDOMHandler() { 87 } 88 89 void 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 101 void 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) 113 void 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 136 ComponentsUI::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 147 ComponentsUI::~ComponentsUI() { 148 component_updater::ComponentUpdateService* cus = 149 g_browser_process->component_updater(); 150 if (cus) 151 cus->RemoveObserver(this); 152 } 153 154 // static 155 void 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 162 base::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 186 base::RefCountedMemory* ComponentsUI::GetFaviconResourceBytes( 187 ui::ScaleFactor scale_factor) { 188 return ResourceBundle::GetSharedInstance(). 189 LoadDataResourceBytesForScale(IDR_PLUGINS_FAVICON, scale_factor); 190 } 191 192 base::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 212 base::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 241 void 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