Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / devtools / device / webrtc / devtools_bridge_client.cc
blob2ca51d00c2a022b7aee29a961deba341b5aca537
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 "base/callback.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/local_discovery/gcd_api_flow.h"
10 #include "chrome/common/url_constants.h"
11 #include "components/signin/core/browser/profile_identity_provider.h"
12 #include "content/public/browser/notification_observer.h"
13 #include "content/public/browser/notification_registrar.h"
14 #include "content/public/browser/notification_source.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_contents_observer.h"
17 #include "content/public/browser/web_contents_user_data.h"
18 #include "ui/base/page_transition_types.h"
20 using content::BrowserThread;
21 using content::WebContents;
23 namespace {
25 const char kBackgroundWorkerURL[] =
26 "chrome://webrtc-device-provider/background_worker.html";
27 const char kSerial[] = "webrtc";
28 const char kPseudoDeviceName[] = "Remote browsers";
29 const char kDeviceIdPrefix[] = "device-id:";
31 class BackgroundWorkerUserData
32 : public content::WebContentsUserData<BackgroundWorkerUserData> {
33 public:
34 DevToolsBridgeClient* client() const { return client_; }
35 void SetClient(DevToolsBridgeClient* client) { client_ = client; }
37 private:
38 friend WebContentsUserData<BackgroundWorkerUserData>;
40 explicit BackgroundWorkerUserData(WebContents* contents) : client_(nullptr) {}
42 DevToolsBridgeClient* client_;
45 } // namespace
47 DEFINE_WEB_CONTENTS_USER_DATA_KEY(BackgroundWorkerUserData);
49 // DevToolsBridgeClient --------------------------------------------------------
51 // static
52 base::WeakPtr<DevToolsBridgeClient> DevToolsBridgeClient::Create(
53 Profile* profile,
54 SigninManagerBase* signin_manager,
55 ProfileOAuth2TokenService* token_service) {
56 DCHECK_CURRENTLY_ON(BrowserThread::UI);
57 auto instance =
58 new DevToolsBridgeClient(profile, signin_manager, token_service);
59 return instance->weak_factory_.GetWeakPtr();
62 DevToolsBridgeClient::DevToolsBridgeClient(
63 Profile* profile,
64 SigninManagerBase* signin_manager,
65 ProfileOAuth2TokenService* token_service)
66 : WebContentsObserver(),
67 profile_(profile),
68 identity_provider_(signin_manager, token_service, base::Closure()),
69 worker_is_loaded_(false),
70 weak_factory_(this) {
71 DCHECK_CURRENTLY_ON(BrowserThread::UI);
73 identity_provider_.AddObserver(this);
74 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
75 content::Source<Profile>(profile_));
77 if (IsAuthenticated())
78 CreateBackgroundWorker();
81 DevToolsBridgeClient::~DevToolsBridgeClient() {
82 DCHECK_CURRENTLY_ON(BrowserThread::UI);
84 identity_provider_.RemoveObserver(this);
87 void DevToolsBridgeClient::DeleteSelf() {
88 DCHECK_CURRENTLY_ON(BrowserThread::UI);
89 delete this;
92 void DevToolsBridgeClient::UpdateBrowserList() {
93 if (!IsAuthenticated() || browser_list_request_.get())
94 return;
95 browser_list_request_ = CreateGCDApiFlow();
96 browser_list_request_->Start(
97 make_scoped_ptr(new DevToolsBridgeInstancesRequest(this)));
100 void DevToolsBridgeClient::StartSessionIfNeeded(
101 const std::string& socket_name) {
102 if (!background_worker_.get() || !background_worker_->GetWebUI() ||
103 !worker_is_loaded_) {
104 return;
107 const size_t kPrefixLength = sizeof(kDeviceIdPrefix) - 1;
108 if (socket_name.substr(0, kPrefixLength) != kDeviceIdPrefix)
109 return;
111 std::string browser_id = socket_name.substr(kPrefixLength);
112 background_worker_->GetWebUI()->CallJavascriptFunction(
113 "WebRTCDeviceProvider.instance.startSessionIfNeeded",
114 base::StringValue(browser_id));
117 // static
118 DevToolsBridgeClient* DevToolsBridgeClient::FromWebContents(
119 WebContents* web_contents) {
120 auto user_data = BackgroundWorkerUserData::FromWebContents(web_contents);
121 return user_data ? user_data->client() : nullptr;
124 void DevToolsBridgeClient::RegisterMessageHandlers(content::WebUI* web_ui) {
125 web_ui->RegisterMessageCallback(
126 "sendCommand", base::Bind(&DevToolsBridgeClient::HandleSendCommand,
127 base::Unretained(this)));
130 bool DevToolsBridgeClient::IsAuthenticated() {
131 return !identity_provider_.GetActiveAccountId().empty();
134 void DevToolsBridgeClient::HandleSendCommand(const base::ListValue* args) {
135 if (args->GetSize() != 1)
136 return;
138 const base::DictionaryValue* command_value;
139 if (!args->GetDictionary(0, &command_value))
140 return;
142 send_command_request_ = CreateGCDApiFlow();
143 send_command_request_->Start(
144 make_scoped_ptr(new SendCommandRequest(command_value, this)));
147 scoped_ptr<local_discovery::GCDApiFlow>
148 DevToolsBridgeClient::CreateGCDApiFlow() {
149 DCHECK(IsAuthenticated());
150 return local_discovery::GCDApiFlow::Create(
151 profile_->GetRequestContext(), identity_provider_.GetTokenService(),
152 identity_provider_.GetActiveAccountId());
155 // static
156 DevToolsBridgeClient::SerialList DevToolsBridgeClient::GetDevices(
157 base::WeakPtr<DevToolsBridgeClient> weak_ptr) {
158 SerialList result;
159 if (auto* ptr = weak_ptr.get()) {
160 if (ptr->background_worker_.get())
161 result.push_back(kSerial);
163 ptr->UpdateBrowserList();
165 return result;
168 // static
169 DevToolsBridgeClient::DeviceInfo DevToolsBridgeClient::GetDeviceInfo(
170 base::WeakPtr<DevToolsBridgeClient> weak_self,
171 const std::string& serial) {
172 DeviceInfo result;
173 if (auto* self = weak_self.get()) {
174 result.connected = !!self->background_worker_.get();
175 result.model = kPseudoDeviceName;
176 result.browser_info = self->browsers_;
178 return result;
181 void DevToolsBridgeClient::CreateBackgroundWorker() {
182 DCHECK_CURRENTLY_ON(BrowserThread::UI);
184 background_worker_.reset(
185 WebContents::Create(WebContents::CreateParams(profile_)));
187 BackgroundWorkerUserData::CreateForWebContents(background_worker_.get());
188 BackgroundWorkerUserData::FromWebContents(background_worker_.get())
189 ->SetClient(this);
190 WebContentsObserver::Observe(background_worker_.get());
192 GURL url(kBackgroundWorkerURL);
193 DCHECK_EQ(chrome::kChromeUIWebRTCDeviceProviderHost, url.host());
195 background_worker_->GetController().LoadURL(url, content::Referrer(),
196 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
197 std::string());
200 void DevToolsBridgeClient::DocumentOnLoadCompletedInMainFrame() {
201 worker_is_loaded_ = true;
204 void DevToolsBridgeClient::Observe(
205 int type,
206 const content::NotificationSource& source,
207 const content::NotificationDetails& details) {
208 DCHECK_CURRENTLY_ON(BrowserThread::UI);
209 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
211 delete this;
214 void DevToolsBridgeClient::OnActiveAccountLogin() {
215 DCHECK_CURRENTLY_ON(BrowserThread::UI);
216 CreateBackgroundWorker();
219 void DevToolsBridgeClient::OnActiveAccountLogout() {
220 DCHECK_CURRENTLY_ON(BrowserThread::UI);
221 background_worker_.reset();
222 browser_list_request_.reset();
223 send_command_request_.reset();
224 BrowserInfoList().swap(browsers_);
225 worker_is_loaded_ = false;
228 void DevToolsBridgeClient::OnCommandSucceeded(
229 const base::DictionaryValue& response) {
230 if (background_worker_.get() && background_worker_->GetWebUI()) {
231 background_worker_->GetWebUI()->CallJavascriptFunction(
232 "WebRTCDeviceProvider.instance.handleCommandSuccess", response);
234 send_command_request_.reset();
237 void DevToolsBridgeClient::OnCommandFailed() {
238 if (background_worker_.get() && background_worker_->GetWebUI()) {
239 background_worker_->GetWebUI()->CallJavascriptFunction(
240 "WebRTCDeviceProvider.instance.handleCommandFailure");
242 send_command_request_.reset();
245 void DevToolsBridgeClient::OnDevToolsBridgeInstancesRequestSucceeded(
246 const DevToolsBridgeInstancesRequest::InstanceList& instances) {
247 BrowserInfoList browsers;
248 for (const auto& instance : instances) {
249 BrowserInfo browser;
250 browser.type = BrowserInfo::kTypeChrome;
251 browser.display_name = instance.display_name;
252 browser.socket_name = kDeviceIdPrefix + instance.id;
253 browsers.push_back(browser);
255 browsers_.swap(browsers);
257 browser_list_request_.reset();
259 OnBrowserListUpdatedForTests();
262 void DevToolsBridgeClient::OnDevToolsBridgeInstancesRequestFailed() {
263 // We keep the list of remote browsers even if the request failed.
264 browser_list_request_.reset();