1 // Copyright 2014 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/gcm_internals_ui.h"
6 
7 #include <memory>
8 #include <vector>
9 
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/macros.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/values.h"
15 #include "chrome/browser/gcm/gcm_profile_service_factory.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/url_constants.h"
18 #include "components/gcm_driver/gcm_client.h"
19 #include "components/gcm_driver/gcm_driver.h"
20 #include "components/gcm_driver/gcm_internals_constants.h"
21 #include "components/gcm_driver/gcm_internals_helper.h"
22 #include "components/gcm_driver/gcm_profile_service.h"
23 #include "components/grit/dev_ui_components_resources.h"
24 #include "content/public/browser/web_ui.h"
25 #include "content/public/browser/web_ui_controller.h"
26 #include "content/public/browser/web_ui_data_source.h"
27 #include "content/public/browser/web_ui_message_handler.h"
28 
29 namespace {
30 
31 // Class acting as a controller of the chrome://gcm-internals WebUI.
32 class GcmInternalsUIMessageHandler : public content::WebUIMessageHandler {
33  public:
34   GcmInternalsUIMessageHandler();
35   ~GcmInternalsUIMessageHandler() override;
36 
37   // WebUIMessageHandler implementation.
38   void RegisterMessages() override;
39 
40  private:
41   // Return all of the GCM related infos to the gcm-internals page by calling
42   // Javascript callback function
43   // |gcm-internals.returnInfo()|.
44   void ReturnResults(Profile* profile, gcm::GCMProfileService* profile_service,
45                      const gcm::GCMClient::GCMStatistics* stats) const;
46 
47   // Request all of the GCM related infos through gcm profile service.
48   void RequestAllInfo(const base::ListValue* args);
49 
50   // Enables/disables GCM activity recording through gcm profile service.
51   void SetRecording(const base::ListValue* args);
52 
53   // Callback function of the request for all gcm related infos.
54   void RequestGCMStatisticsFinished(
55       const gcm::GCMClient::GCMStatistics& args) const;
56 
57   // Factory for creating references in callbacks.
58   base::WeakPtrFactory<GcmInternalsUIMessageHandler> weak_ptr_factory_{this};
59 
60   DISALLOW_COPY_AND_ASSIGN(GcmInternalsUIMessageHandler);
61 };
62 
GcmInternalsUIMessageHandler()63 GcmInternalsUIMessageHandler::GcmInternalsUIMessageHandler() {}
64 
~GcmInternalsUIMessageHandler()65 GcmInternalsUIMessageHandler::~GcmInternalsUIMessageHandler() {}
66 
ReturnResults(Profile * profile,gcm::GCMProfileService * profile_service,const gcm::GCMClient::GCMStatistics * stats) const67 void GcmInternalsUIMessageHandler::ReturnResults(
68     Profile* profile,
69     gcm::GCMProfileService* profile_service,
70     const gcm::GCMClient::GCMStatistics* stats) const {
71   base::DictionaryValue results;
72   gcm_driver::SetGCMInternalsInfo(stats, profile_service, profile->GetPrefs(),
73                                   &results);
74   web_ui()->CallJavascriptFunctionUnsafe(gcm_driver::kSetGcmInternalsInfo,
75                                          results);
76 }
77 
RequestAllInfo(const base::ListValue * args)78 void GcmInternalsUIMessageHandler::RequestAllInfo(
79     const base::ListValue* args) {
80   if (args->GetSize() != 1) {
81     NOTREACHED();
82     return;
83   }
84   bool clear_logs = false;
85   if (!args->GetBoolean(0, &clear_logs)) {
86     NOTREACHED();
87     return;
88   }
89 
90   gcm::GCMDriver::ClearActivityLogs clear_activity_logs =
91       clear_logs ? gcm::GCMDriver::CLEAR_LOGS : gcm::GCMDriver::KEEP_LOGS;
92 
93   Profile* profile = Profile::FromWebUI(web_ui());
94   gcm::GCMProfileService* profile_service =
95     gcm::GCMProfileServiceFactory::GetForProfile(profile);
96 
97   if (!profile_service || !profile_service->driver()) {
98     ReturnResults(profile, NULL, NULL);
99   } else {
100     profile_service->driver()->GetGCMStatistics(
101         base::Bind(&GcmInternalsUIMessageHandler::RequestGCMStatisticsFinished,
102                    weak_ptr_factory_.GetWeakPtr()),
103         clear_activity_logs);
104   }
105 }
106 
SetRecording(const base::ListValue * args)107 void GcmInternalsUIMessageHandler::SetRecording(const base::ListValue* args) {
108   if (args->GetSize() != 1) {
109     NOTREACHED();
110     return;
111   }
112   bool recording = false;
113   if (!args->GetBoolean(0, &recording)) {
114     NOTREACHED();
115     return;
116   }
117 
118   Profile* profile = Profile::FromWebUI(web_ui());
119   gcm::GCMProfileService* profile_service =
120       gcm::GCMProfileServiceFactory::GetForProfile(profile);
121 
122   if (!profile_service) {
123     ReturnResults(profile, NULL, NULL);
124     return;
125   }
126   // Get fresh stats after changing recording setting.
127   profile_service->driver()->SetGCMRecording(
128       base::Bind(
129           &GcmInternalsUIMessageHandler::RequestGCMStatisticsFinished,
130           weak_ptr_factory_.GetWeakPtr()),
131       recording);
132 }
133 
RequestGCMStatisticsFinished(const gcm::GCMClient::GCMStatistics & stats) const134 void GcmInternalsUIMessageHandler::RequestGCMStatisticsFinished(
135     const gcm::GCMClient::GCMStatistics& stats) const {
136   Profile* profile = Profile::FromWebUI(web_ui());
137   DCHECK(profile);
138   gcm::GCMProfileService* profile_service =
139       gcm::GCMProfileServiceFactory::GetForProfile(profile);
140   DCHECK(profile_service);
141   ReturnResults(profile, profile_service, &stats);
142 }
143 
RegisterMessages()144 void GcmInternalsUIMessageHandler::RegisterMessages() {
145   web_ui()->RegisterMessageCallback(
146       gcm_driver::kGetGcmInternalsInfo,
147       base::BindRepeating(&GcmInternalsUIMessageHandler::RequestAllInfo,
148                           weak_ptr_factory_.GetWeakPtr()));
149   web_ui()->RegisterMessageCallback(
150       gcm_driver::kSetGcmInternalsRecording,
151       base::BindRepeating(&GcmInternalsUIMessageHandler::SetRecording,
152                           weak_ptr_factory_.GetWeakPtr()));
153 }
154 
155 }  // namespace
156 
GCMInternalsUI(content::WebUI * web_ui)157 GCMInternalsUI::GCMInternalsUI(content::WebUI* web_ui)
158     : content::WebUIController(web_ui) {
159   // Set up the chrome://gcm-internals source.
160   content::WebUIDataSource* html_source =
161       content::WebUIDataSource::Create(chrome::kChromeUIGCMInternalsHost);
162 
163   html_source->UseStringsJs();
164 
165   // Add required resources.
166   html_source->AddResourcePath(gcm_driver::kGcmInternalsCSS,
167                                IDR_GCM_DRIVER_GCM_INTERNALS_CSS);
168   html_source->AddResourcePath(gcm_driver::kGcmInternalsJS,
169                                IDR_GCM_DRIVER_GCM_INTERNALS_JS);
170   html_source->SetDefaultResource(IDR_GCM_DRIVER_GCM_INTERNALS_HTML);
171 
172   Profile* profile = Profile::FromWebUI(web_ui);
173   content::WebUIDataSource::Add(profile, html_source);
174 
175   web_ui->AddMessageHandler(std::make_unique<GcmInternalsUIMessageHandler>());
176 }
177 
~GCMInternalsUI()178 GCMInternalsUI::~GCMInternalsUI() {}
179