1 // Copyright 2019 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/components_handler.h"
6 
7 #include "base/bind.h"
8 #include "base/values.h"
9 #include "chrome/grit/generated_resources.h"
10 #include "components/update_client/crx_update_item.h"
11 #include "ui/base/l10n/l10n_util.h"
12 
ComponentsHandler(component_updater::ComponentUpdateService * component_updater)13 ComponentsHandler::ComponentsHandler(
14     component_updater::ComponentUpdateService* component_updater)
15     : component_updater_(component_updater) {
16   DCHECK(component_updater_);
17 }
18 ComponentsHandler::~ComponentsHandler() = default;
19 
RegisterMessages()20 void ComponentsHandler::RegisterMessages() {
21   web_ui()->RegisterMessageCallback(
22       "requestComponentsData",
23       base::BindRepeating(&ComponentsHandler::HandleRequestComponentsData,
24                           base::Unretained(this)));
25 
26   web_ui()->RegisterMessageCallback(
27       "checkUpdate", base::BindRepeating(&ComponentsHandler::HandleCheckUpdate,
28                                          base::Unretained(this)));
29 }
30 
OnJavascriptAllowed()31 void ComponentsHandler::OnJavascriptAllowed() {
32   observer_.Add(component_updater_);
33 }
34 
OnJavascriptDisallowed()35 void ComponentsHandler::OnJavascriptDisallowed() {
36   observer_.RemoveAll();
37 }
38 
HandleRequestComponentsData(const base::ListValue * args)39 void ComponentsHandler::HandleRequestComponentsData(
40     const base::ListValue* args) {
41   AllowJavascript();
42   const base::Value& callback_id = args->GetList()[0];
43 
44   base::DictionaryValue result;
45   result.Set("components", LoadComponents());
46   ResolveJavascriptCallback(callback_id, result);
47 }
48 
49 // This function is called when user presses button from html UI.
50 // TODO(shrikant): We need to make this button available based on current
51 // state e.g. If component state is currently updating then we need to disable
52 // button. (https://code.google.com/p/chromium/issues/detail?id=272540)
HandleCheckUpdate(const base::ListValue * args)53 void ComponentsHandler::HandleCheckUpdate(const base::ListValue* args) {
54   if (args->GetSize() != 1) {
55     NOTREACHED();
56     return;
57   }
58 
59   std::string component_id;
60   if (!args->GetString(0, &component_id)) {
61     NOTREACHED();
62     return;
63   }
64 
65   OnDemandUpdate(component_id);
66 }
67 
OnEvent(Events event,const std::string & id)68 void ComponentsHandler::OnEvent(Events event, const std::string& id) {
69   base::DictionaryValue parameters;
70   parameters.SetString("event", ComponentEventToString(event));
71   if (!id.empty()) {
72     if (event == Events::COMPONENT_UPDATED) {
73       update_client::CrxUpdateItem item;
74       if (component_updater_->GetComponentDetails(id, &item) && item.component)
75         parameters.SetString("version", item.component->version.GetString());
76     }
77     parameters.SetString("id", id);
78   }
79   FireWebUIListener("component-event", parameters);
80 }
81 
ComponentEventToString(Events event)82 base::string16 ComponentsHandler::ComponentEventToString(Events event) {
83   switch (event) {
84     case Events::COMPONENT_CHECKING_FOR_UPDATES:
85       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_STARTED);
86     case Events::COMPONENT_WAIT:
87       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_SLEEPING);
88     case Events::COMPONENT_UPDATE_FOUND:
89       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_FOUND);
90     case Events::COMPONENT_UPDATE_READY:
91       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_READY);
92     case Events::COMPONENT_UPDATED:
93       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_UPDATED);
94     case Events::COMPONENT_NOT_UPDATED:
95       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_NOTUPDATED);
96     case Events::COMPONENT_UPDATE_ERROR:
97       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_UPDATE_ERROR);
98     case Events::COMPONENT_UPDATE_DOWNLOADING:
99       return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_DOWNLOADING);
100   }
101   return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
102 }
103 
ServiceStatusToString(update_client::ComponentState state)104 base::string16 ComponentsHandler::ServiceStatusToString(
105     update_client::ComponentState state) {
106   // TODO(sorin): handle kDownloaded. For now, just handle it as kUpdating.
107   switch (state) {
108     case update_client::ComponentState::kNew:
109       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_NEW);
110     case update_client::ComponentState::kChecking:
111       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_CHECKING);
112     case update_client::ComponentState::kCanUpdate:
113       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE);
114     case update_client::ComponentState::kDownloadingDiff:
115       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL_DIFF);
116     case update_client::ComponentState::kDownloading:
117       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL);
118     case update_client::ComponentState::kUpdatingDiff:
119       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDT_DIFF);
120     case update_client::ComponentState::kUpdating:
121       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATING);
122     case update_client::ComponentState::kDownloaded:
123       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DOWNLOADED);
124     case update_client::ComponentState::kUpdated:
125       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATED);
126     case update_client::ComponentState::kUpToDate:
127       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPTODATE);
128     case update_client::ComponentState::kUpdateError:
129       return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE_ERROR);
130     case update_client::ComponentState::kUninstalled:  // Fall through.
131     case update_client::ComponentState::kRun:
132     case update_client::ComponentState::kLastStatus:
133       return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
134   }
135   return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
136 }
137 
OnDemandUpdate(const std::string & component_id)138 void ComponentsHandler::OnDemandUpdate(const std::string& component_id) {
139   component_updater_->GetOnDemandUpdater().OnDemandUpdate(
140       component_id, component_updater::OnDemandUpdater::Priority::FOREGROUND,
141       component_updater::Callback());
142 }
143 
LoadComponents()144 std::unique_ptr<base::ListValue> ComponentsHandler::LoadComponents() {
145   std::vector<std::string> component_ids;
146   component_ids = component_updater_->GetComponentIDs();
147 
148   // Construct DictionaryValues to return to UI.
149   auto component_list = std::make_unique<base::ListValue>();
150   for (size_t j = 0; j < component_ids.size(); ++j) {
151     update_client::CrxUpdateItem item;
152     if (component_updater_->GetComponentDetails(component_ids[j], &item)) {
153       auto component_entry = std::make_unique<base::DictionaryValue>();
154       component_entry->SetString("id", component_ids[j]);
155       component_entry->SetString("status", ServiceStatusToString(item.state));
156       if (item.component) {
157         component_entry->SetString("name", item.component->name);
158         component_entry->SetString("version",
159                                    item.component->version.GetString());
160       }
161       component_list->Append(std::move(component_entry));
162     }
163   }
164 
165   return component_list;
166 }
167