1 // Copyright 2020 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/nearby_internals/nearby_internals_http_handler.h"
6
7 #include "base/bind.h"
8 #include "base/json/json_writer.h"
9 #include "base/time/time.h"
10 #include "base/values.h"
11 #include "chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager.h"
12 #include "chrome/browser/nearby_sharing/client/nearby_share_http_notifier.h"
13 #include "chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager.h"
14 #include "chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.h"
15 #include "chrome/browser/nearby_sharing/logging/logging.h"
16 #include "chrome/browser/nearby_sharing/logging/proto_to_dictionary_conversion.h"
17 #include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
18 #include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
19
20 namespace {
21
22 // This enum class needs to stay in sync with the Rpc definition in
23 // chrome/browser/resources/nearby_internals/types.js.
24 enum class Rpc {
25 kCertificate = 0,
26 kContact = 1,
27 kDevice = 2,
28 kDeviceState = 3
29 };
30
31 // This enum class needs to stay in sync with the Direction definition in
32 // chrome/browser/resources/nearby_internals/types.js.
33 enum class Direction { kRequest = 0, kResponse = 1 };
34
FormatAsJSON(const base::Value & value)35 std::string FormatAsJSON(const base::Value& value) {
36 std::string json;
37 base::JSONWriter::WriteWithOptions(
38 value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
39 return json;
40 }
41
GetJavascriptTimestamp()42 base::Value GetJavascriptTimestamp() {
43 return base::Value(base::Time::Now().ToJsTimeIgnoringNull());
44 }
45
46 // FireWebUIListener message to notify the JavaScript of HTTP message addition.
47 const char kHttpMessageAdded[] = "http-message-added";
48
49 // Keys in the JSON representation of a Http Message
50 const char kHttpMessageBodyKey[] = "body";
51 const char kHttpMessageTimeKey[] = "time";
52 const char kHttpMessageRpcKey[] = "rpc";
53 const char kHttpMessageDirectionKey[] = "direction";
54
55 // Converts a RPC request/response to a raw dictionary value used as a
56 // JSON argument to JavaScript functions.
HttpMessageToDictionary(const base::Value & message,Direction dir,Rpc rpc)57 base::Value HttpMessageToDictionary(const base::Value& message,
58 Direction dir,
59 Rpc rpc) {
60 base::Value dictionary(base::Value::Type::DICTIONARY);
61 dictionary.SetStringKey(kHttpMessageBodyKey, FormatAsJSON(message));
62 dictionary.SetKey(kHttpMessageTimeKey, GetJavascriptTimestamp());
63 dictionary.SetIntKey(kHttpMessageRpcKey, static_cast<int>(rpc));
64 dictionary.SetIntKey(kHttpMessageDirectionKey, static_cast<int>(dir));
65 return dictionary;
66 }
67
68 } // namespace
69
NearbyInternalsHttpHandler(content::BrowserContext * context)70 NearbyInternalsHttpHandler::NearbyInternalsHttpHandler(
71 content::BrowserContext* context)
72 : context_(context) {}
73
74 NearbyInternalsHttpHandler::~NearbyInternalsHttpHandler() = default;
75
RegisterMessages()76 void NearbyInternalsHttpHandler::RegisterMessages() {
77 web_ui()->RegisterMessageCallback(
78 "initializeHttp",
79 base::BindRepeating(&NearbyInternalsHttpHandler::InitializeContents,
80 base::Unretained(this)));
81 web_ui()->RegisterMessageCallback(
82 "updateDevice",
83 base::BindRepeating(&NearbyInternalsHttpHandler::UpdateDevice,
84 base::Unretained(this)));
85 web_ui()->RegisterMessageCallback(
86 "listContactPeople",
87 base::BindRepeating(&NearbyInternalsHttpHandler::ListContactPeople,
88 base::Unretained(this)));
89 web_ui()->RegisterMessageCallback(
90 "listPublicCertificates",
91 base::BindRepeating(&NearbyInternalsHttpHandler::ListPublicCertificates,
92 base::Unretained(this)));
93 }
94
OnJavascriptAllowed()95 void NearbyInternalsHttpHandler::OnJavascriptAllowed() {
96 NearbySharingService* service_ =
97 NearbySharingServiceFactory::GetForBrowserContext(context_);
98 if (service_) {
99 observer_.Add(service_->GetHttpNotifier());
100 } else {
101 NS_LOG(ERROR) << "No NearbyShareService instance to call.";
102 }
103 }
104
OnJavascriptDisallowed()105 void NearbyInternalsHttpHandler::OnJavascriptDisallowed() {
106 observer_.RemoveAll();
107 }
108
InitializeContents(const base::ListValue * args)109 void NearbyInternalsHttpHandler::InitializeContents(
110 const base::ListValue* args) {
111 AllowJavascript();
112 }
113
UpdateDevice(const base::ListValue * args)114 void NearbyInternalsHttpHandler::UpdateDevice(const base::ListValue* args) {
115 NearbySharingService* service_ =
116 NearbySharingServiceFactory::GetForBrowserContext(context_);
117 if (service_) {
118 service_->GetLocalDeviceDataManager()->DownloadDeviceData();
119 } else {
120 NS_LOG(ERROR) << "No NearbyShareService instance to call.";
121 }
122 }
123
ListPublicCertificates(const base::ListValue * args)124 void NearbyInternalsHttpHandler::ListPublicCertificates(
125 const base::ListValue* args) {
126 NearbySharingService* service_ =
127 NearbySharingServiceFactory::GetForBrowserContext(context_);
128 if (service_) {
129 service_->GetCertificateManager()->DownloadPublicCertificates();
130 } else {
131 NS_LOG(ERROR) << "No NearbyShareService instance to call.";
132 }
133 }
134
ListContactPeople(const base::ListValue * args)135 void NearbyInternalsHttpHandler::ListContactPeople(
136 const base::ListValue* args) {
137 NearbySharingService* service_ =
138 NearbySharingServiceFactory::GetForBrowserContext(context_);
139 if (service_) {
140 service_->GetContactManager()->DownloadContacts();
141 } else {
142 NS_LOG(ERROR) << "No NearbyShareService instance to call.";
143 }
144 }
145
OnUpdateDeviceRequest(const nearbyshare::proto::UpdateDeviceRequest & request)146 void NearbyInternalsHttpHandler::OnUpdateDeviceRequest(
147 const nearbyshare::proto::UpdateDeviceRequest& request) {
148 FireWebUIListener(
149 kHttpMessageAdded,
150 HttpMessageToDictionary(UpdateDeviceRequestToReadableDictionary(request),
151 Direction::kRequest, Rpc::kDevice));
152 }
153
OnUpdateDeviceResponse(const nearbyshare::proto::UpdateDeviceResponse & response)154 void NearbyInternalsHttpHandler::OnUpdateDeviceResponse(
155 const nearbyshare::proto::UpdateDeviceResponse& response) {
156 FireWebUIListener(kHttpMessageAdded,
157 HttpMessageToDictionary(
158 UpdateDeviceResponseToReadableDictionary(response),
159 Direction::kResponse, Rpc::kDevice));
160 }
161
OnListContactPeopleRequest(const nearbyshare::proto::ListContactPeopleRequest & request)162 void NearbyInternalsHttpHandler::OnListContactPeopleRequest(
163 const nearbyshare::proto::ListContactPeopleRequest& request) {
164 FireWebUIListener(kHttpMessageAdded,
165 HttpMessageToDictionary(
166 ListContactPeopleRequestToReadableDictionary(request),
167 Direction::kRequest, Rpc::kContact));
168 }
169
OnListContactPeopleResponse(const nearbyshare::proto::ListContactPeopleResponse & response)170 void NearbyInternalsHttpHandler::OnListContactPeopleResponse(
171 const nearbyshare::proto::ListContactPeopleResponse& response) {
172 FireWebUIListener(kHttpMessageAdded,
173 HttpMessageToDictionary(
174 ListContactPeopleResponseToReadableDictionary(response),
175 Direction::kResponse, Rpc::kContact));
176 }
177
OnListPublicCertificatesRequest(const nearbyshare::proto::ListPublicCertificatesRequest & request)178 void NearbyInternalsHttpHandler::OnListPublicCertificatesRequest(
179 const nearbyshare::proto::ListPublicCertificatesRequest& request) {
180 FireWebUIListener(
181 kHttpMessageAdded,
182 HttpMessageToDictionary(
183 ListPublicCertificatesRequestToReadableDictionary(request),
184 Direction::kRequest, Rpc::kCertificate));
185 }
186
OnListPublicCertificatesResponse(const nearbyshare::proto::ListPublicCertificatesResponse & response)187 void NearbyInternalsHttpHandler::OnListPublicCertificatesResponse(
188 const nearbyshare::proto::ListPublicCertificatesResponse& response) {
189 FireWebUIListener(
190 kHttpMessageAdded,
191 HttpMessageToDictionary(
192 ListPublicCertificatesResponseToReadableDictionary(response),
193 Direction::kResponse, Rpc::kCertificate));
194 }
195