[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / chrome / browser / devtools / device / webrtc / devtools_bridge_client.cc
blob99af8a05c12f1c7df23ec5f1d664a6a40b912657
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.
5 #include "chrome/browser/devtools/device/webrtc/devtools_bridge_client.h"
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/local_discovery/gcd_api_flow.h"
9 #include "chrome/browser/signin/profile_identity_provider.h"
10 #include "chrome/common/url_constants.h"
11 #include "content/public/browser/notification_observer.h"
12 #include "content/public/browser/notification_registrar.h"
13 #include "content/public/browser/notification_source.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_observer.h"
16 #include "content/public/browser/web_contents_user_data.h"
17 #include "ui/base/page_transition_types.h"
19 using content::BrowserThread;
20 using content::WebContents;
22 namespace {
24 const char kBackgroundWorkerURL[] =
25 "chrome://webrtc-device-provider/background_worker.html";
26 const char kSerial[] = "webrtc";
27 const char kPseudoDeviceName[] = "Remote browsers";
28 const char kDeviceIdPrefix[] = "device-id:";
30 class BackgroundWorkerUserData
31 : public content::WebContentsUserData<BackgroundWorkerUserData> {
32 public:
33 DevToolsBridgeClient* client() const { return client_; }
34 void SetClient(DevToolsBridgeClient* client) { client_ = client; }
36 private:
37 friend WebContentsUserData<BackgroundWorkerUserData>;
39 explicit BackgroundWorkerUserData(WebContents* contents) : client_(nullptr) {}
41 DevToolsBridgeClient* client_;
44 } // namespace
46 DEFINE_WEB_CONTENTS_USER_DATA_KEY(BackgroundWorkerUserData);
48 // DevToolsBridgeClient --------------------------------------------------------
50 // static
51 base::WeakPtr<DevToolsBridgeClient> DevToolsBridgeClient::Create(
52 Profile* profile,
53 SigninManagerBase* signin_manager,
54 ProfileOAuth2TokenService* token_service) {
55 DCHECK_CURRENTLY_ON(BrowserThread::UI);
56 auto instance =
57 new DevToolsBridgeClient(profile, signin_manager, token_service);
58 return instance->weak_factory_.GetWeakPtr();
61 DevToolsBridgeClient::DevToolsBridgeClient(
62 Profile* profile,
63 SigninManagerBase* signin_manager,
64 ProfileOAuth2TokenService* token_service)
65 : WebContentsObserver(),
66 profile_(profile),
67 identity_provider_(signin_manager, token_service, nullptr),
68 worker_is_loaded_(false),
69 weak_factory_(this) {
70 DCHECK_CURRENTLY_ON(BrowserThread::UI);
72 identity_provider_.AddObserver(this);
73 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
74 content::Source<Profile>(profile_));
76 if (IsAuthenticated())
77 CreateBackgroundWorker();
80 DevToolsBridgeClient::~DevToolsBridgeClient() {
81 DCHECK_CURRENTLY_ON(BrowserThread::UI);
83 identity_provider_.RemoveObserver(this);
86 void DevToolsBridgeClient::DeleteSelf() {
87 DCHECK_CURRENTLY_ON(BrowserThread::UI);
88 delete this;
91 void DevToolsBridgeClient::UpdateBrowserList() {
92 if (!IsAuthenticated() || browser_list_request_.get())
93 return;
94 browser_list_request_ = CreateGCDApiFlow();
95 browser_list_request_->Start(
96 make_scoped_ptr(new DevToolsBridgeInstancesRequest(this)));
99 void DevToolsBridgeClient::StartSessionIfNeeded(
100 const std::string& socket_name) {
101 if (!background_worker_.get() || !background_worker_->GetWebUI() ||
102 !worker_is_loaded_) {
103 return;
106 const size_t kPrefixLength = sizeof(kDeviceIdPrefix) - 1;
107 if (socket_name.substr(0, kPrefixLength) != kDeviceIdPrefix)
108 return;
110 std::string browser_id = socket_name.substr(kPrefixLength);
111 background_worker_->GetWebUI()->CallJavascriptFunction(
112 "WebRTCDeviceProvider.instance.startSessionIfNeeded",
113 base::StringValue(browser_id));
116 // static
117 DevToolsBridgeClient* DevToolsBridgeClient::FromWebContents(
118 WebContents* web_contents) {
119 auto user_data = BackgroundWorkerUserData::FromWebContents(web_contents);
120 return user_data ? user_data->client() : nullptr;
123 void DevToolsBridgeClient::RegisterMessageHandlers(content::WebUI* web_ui) {
124 web_ui->RegisterMessageCallback(
125 "sendCommand", base::Bind(&DevToolsBridgeClient::HandleSendCommand,
126 base::Unretained(this)));
129 bool DevToolsBridgeClient::IsAuthenticated() {
130 return !identity_provider_.GetActiveAccountId().empty();
133 void DevToolsBridgeClient::HandleSendCommand(const base::ListValue* args) {
134 if (args->GetSize() != 1)
135 return;
137 const base::DictionaryValue* command_value;
138 if (!args->GetDictionary(0, &command_value))
139 return;
141 send_command_request_ = CreateGCDApiFlow();
142 send_command_request_->Start(
143 make_scoped_ptr(new SendCommandRequest(command_value, this)));
146 scoped_ptr<local_discovery::GCDApiFlow>
147 DevToolsBridgeClient::CreateGCDApiFlow() {
148 DCHECK(IsAuthenticated());
149 return local_discovery::GCDApiFlow::Create(
150 profile_->GetRequestContext(), identity_provider_.GetTokenService(),
151 identity_provider_.GetActiveAccountId());
154 // static
155 DevToolsBridgeClient::SerialList DevToolsBridgeClient::GetDevices(
156 base::WeakPtr<DevToolsBridgeClient> weak_ptr) {
157 SerialList result;
158 if (auto* ptr = weak_ptr.get()) {
159 if (ptr->background_worker_.get())
160 result.push_back(kSerial);
162 ptr->UpdateBrowserList();
164 return result;
167 // static
168 DevToolsBridgeClient::DeviceInfo DevToolsBridgeClient::GetDeviceInfo(
169 base::WeakPtr<DevToolsBridgeClient> weak_self,
170 const std::string& serial) {
171 DeviceInfo result;
172 if (auto* self = weak_self.get()) {
173 result.connected = !!self->background_worker_.get();
174 result.model = kPseudoDeviceName;
175 result.browser_info = self->browsers_;
177 return result;
180 void DevToolsBridgeClient::CreateBackgroundWorker() {
181 DCHECK_CURRENTLY_ON(BrowserThread::UI);
183 background_worker_.reset(
184 WebContents::Create(WebContents::CreateParams(profile_)));
186 BackgroundWorkerUserData::CreateForWebContents(background_worker_.get());
187 BackgroundWorkerUserData::FromWebContents(background_worker_.get())
188 ->SetClient(this);
189 WebContentsObserver::Observe(background_worker_.get());
191 GURL url(kBackgroundWorkerURL);
192 DCHECK_EQ(chrome::kChromeUIWebRTCDeviceProviderHost, url.host());
194 background_worker_->GetController().LoadURL(url, content::Referrer(),
195 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
196 std::string());
199 void DevToolsBridgeClient::DocumentOnLoadCompletedInMainFrame() {
200 worker_is_loaded_ = true;
203 void DevToolsBridgeClient::Observe(
204 int type,
205 const content::NotificationSource& source,
206 const content::NotificationDetails& details) {
207 DCHECK_CURRENTLY_ON(BrowserThread::UI);
208 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
210 delete this;
213 void DevToolsBridgeClient::OnActiveAccountLogin() {
214 DCHECK_CURRENTLY_ON(BrowserThread::UI);
215 CreateBackgroundWorker();
218 void DevToolsBridgeClient::OnActiveAccountLogout() {
219 DCHECK_CURRENTLY_ON(BrowserThread::UI);
220 background_worker_.reset();
221 browser_list_request_.reset();
222 send_command_request_.reset();
223 BrowserInfoList().swap(browsers_);
224 worker_is_loaded_ = false;
227 void DevToolsBridgeClient::OnCommandSucceeded(
228 const base::DictionaryValue& response) {
229 if (background_worker_.get() && background_worker_->GetWebUI()) {
230 background_worker_->GetWebUI()->CallJavascriptFunction(
231 "WebRTCDeviceProvider.instance.handleCommandSuccess", response);
233 send_command_request_.reset();
236 void DevToolsBridgeClient::OnCommandFailed() {
237 if (background_worker_.get() && background_worker_->GetWebUI()) {
238 background_worker_->GetWebUI()->CallJavascriptFunction(
239 "WebRTCDeviceProvider.instance.handleCommandFailure");
241 send_command_request_.reset();
244 void DevToolsBridgeClient::OnDevToolsBridgeInstancesRequestSucceeded(
245 const DevToolsBridgeInstancesRequest::InstanceList& instances) {
246 BrowserInfoList browsers;
247 for (const auto& instance : instances) {
248 BrowserInfo browser;
249 browser.type = BrowserInfo::kTypeChrome;
250 browser.display_name = instance.display_name;
251 browser.socket_name = kDeviceIdPrefix + instance.id;
252 browsers.push_back(browser);
254 browsers_.swap(browsers);
256 browser_list_request_.reset();
258 OnBrowserListUpdatedForTests();
261 void DevToolsBridgeClient::OnDevToolsBridgeInstancesRequestFailed() {
262 // We keep the list of remote browsers even if the request failed.
263 browser_list_request_.reset();