blob: ff606ccdf19437781cfbcab994d7ef59899c45a6 [file] [log] [blame]
[email protected]44ecb832013-08-02 09:06:451// Copyright 2013 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
[email protected]29998f92014-06-15 03:12:145#include "chrome/browser/media/midi_permission_context.h"
[email protected]44ecb832013-08-02 09:06:456
7#include "base/prefs/pref_service.h"
8#include "chrome/browser/content_settings/host_content_settings_map.h"
9#include "chrome/browser/content_settings/permission_queue_controller.h"
10#include "chrome/browser/content_settings/permission_request_id.h"
11#include "chrome/browser/content_settings/tab_specific_content_settings.h"
12#include "chrome/browser/profiles/profile.h"
13#include "chrome/browser/tab_contents/tab_util.h"
[email protected]7babfcbe2014-02-12 22:56:3814#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
15#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
16#include "chrome/common/pref_names.h"
[email protected]44ecb832013-08-02 09:06:4517#include "content/public/browser/browser_thread.h"
[email protected]29998f92014-06-15 03:12:1418#include "content/public/browser/render_process_host.h"
19#include "content/public/browser/render_view_host.h"
[email protected]44ecb832013-08-02 09:06:4520#include "content/public/browser/web_contents.h"
[email protected]7babfcbe2014-02-12 22:56:3821#include "grit/generated_resources.h"
[email protected]d23cdeee2014-03-10 06:39:5322#include "grit/theme_resources.h"
[email protected]7babfcbe2014-02-12 22:56:3823#include "net/base/net_util.h"
24#include "ui/base/l10n/l10n_util.h"
25
26class MidiPermissionRequest : public PermissionBubbleRequest {
27 public:
28 MidiPermissionRequest(
[email protected]29998f92014-06-15 03:12:1429 MidiPermissionContext* context,
[email protected]7babfcbe2014-02-12 22:56:3830 const PermissionRequestID& id,
31 const GURL& requesting_frame,
[email protected]7c6d9482014-03-28 20:19:3132 bool user_gesture,
[email protected]7babfcbe2014-02-12 22:56:3833 const std::string& display_languages,
[email protected]29998f92014-06-15 03:12:1434 const base::Callback<void(bool)>& callback);
[email protected]7babfcbe2014-02-12 22:56:3835 virtual ~MidiPermissionRequest();
36
37 // PermissionBubbleDelegate:
[email protected]d23cdeee2014-03-10 06:39:5338 virtual int GetIconID() const OVERRIDE;
[email protected]7babfcbe2014-02-12 22:56:3839 virtual base::string16 GetMessageText() const OVERRIDE;
40 virtual base::string16 GetMessageTextFragment() const OVERRIDE;
[email protected]d23cdeee2014-03-10 06:39:5341 virtual bool HasUserGesture() const OVERRIDE;
42 virtual GURL GetRequestingHostname() const OVERRIDE;
[email protected]7babfcbe2014-02-12 22:56:3843 virtual void PermissionGranted() OVERRIDE;
44 virtual void PermissionDenied() OVERRIDE;
45 virtual void Cancelled() OVERRIDE;
46 virtual void RequestFinished() OVERRIDE;
47
48 private:
[email protected]29998f92014-06-15 03:12:1449 MidiPermissionContext* context_;
[email protected]7babfcbe2014-02-12 22:56:3850 const PermissionRequestID id_;
51 GURL requesting_frame_;
[email protected]7c6d9482014-03-28 20:19:3152 bool user_gesture_;
[email protected]7babfcbe2014-02-12 22:56:3853 std::string display_languages_;
[email protected]29998f92014-06-15 03:12:1454 const base::Callback<void(bool)>& callback_;
[email protected]1b6a1c22014-05-27 23:23:1455 bool is_finished_;
[email protected]7babfcbe2014-02-12 22:56:3856
57 DISALLOW_COPY_AND_ASSIGN(MidiPermissionRequest);
58};
59
60MidiPermissionRequest::MidiPermissionRequest(
[email protected]29998f92014-06-15 03:12:1461 MidiPermissionContext* context,
[email protected]7babfcbe2014-02-12 22:56:3862 const PermissionRequestID& id,
63 const GURL& requesting_frame,
[email protected]7c6d9482014-03-28 20:19:3164 bool user_gesture,
[email protected]7babfcbe2014-02-12 22:56:3865 const std::string& display_languages,
[email protected]29998f92014-06-15 03:12:1466 const base::Callback<void(bool)>& callback)
[email protected]7babfcbe2014-02-12 22:56:3867 : context_(context),
68 id_(id),
69 requesting_frame_(requesting_frame),
[email protected]7c6d9482014-03-28 20:19:3170 user_gesture_(user_gesture),
[email protected]7babfcbe2014-02-12 22:56:3871 display_languages_(display_languages),
[email protected]1b6a1c22014-05-27 23:23:1472 callback_(callback),
73 is_finished_(false) {}
[email protected]7babfcbe2014-02-12 22:56:3874
[email protected]1b6a1c22014-05-27 23:23:1475MidiPermissionRequest::~MidiPermissionRequest() {
76 DCHECK(is_finished_);
77}
[email protected]7babfcbe2014-02-12 22:56:3878
[email protected]d23cdeee2014-03-10 06:39:5379int MidiPermissionRequest::GetIconID() const {
80 return IDR_ALLOWED_MIDI_SYSEX;
81}
82
[email protected]7babfcbe2014-02-12 22:56:3883base::string16 MidiPermissionRequest::GetMessageText() const {
84 return l10n_util::GetStringFUTF16(
85 IDS_MIDI_SYSEX_INFOBAR_QUESTION,
86 net::FormatUrl(requesting_frame_.GetOrigin(), display_languages_));
87}
88
89base::string16 MidiPermissionRequest::GetMessageTextFragment() const {
90 return l10n_util::GetStringUTF16(IDS_MIDI_SYSEX_PERMISSION_FRAGMENT);
91}
92
[email protected]d23cdeee2014-03-10 06:39:5393bool MidiPermissionRequest::HasUserGesture() const {
[email protected]7c6d9482014-03-28 20:19:3194 return user_gesture_;
[email protected]7babfcbe2014-02-12 22:56:3895}
96
[email protected]d23cdeee2014-03-10 06:39:5397GURL MidiPermissionRequest::GetRequestingHostname() const {
98 return requesting_frame_;
[email protected]7babfcbe2014-02-12 22:56:3899}
100
101void MidiPermissionRequest::PermissionGranted() {
102 context_->NotifyPermissionSet(id_, requesting_frame_, callback_, true);
103}
104
105void MidiPermissionRequest::PermissionDenied() {
106 context_->NotifyPermissionSet(id_, requesting_frame_, callback_, false);
107}
108
109void MidiPermissionRequest::Cancelled() {
[email protected]7babfcbe2014-02-12 22:56:38110}
111
112void MidiPermissionRequest::RequestFinished() {
[email protected]1b6a1c22014-05-27 23:23:14113 is_finished_ = true;
114 // Deletes 'this'.
115 context_->RequestFinished(this);
[email protected]7babfcbe2014-02-12 22:56:38116}
[email protected]44ecb832013-08-02 09:06:45117
[email protected]29998f92014-06-15 03:12:14118MidiPermissionContext::MidiPermissionContext(Profile* profile)
[email protected]44ecb832013-08-02 09:06:45119 : profile_(profile),
[email protected]29998f92014-06-15 03:12:14120 shutting_down_(false),
121 weak_factory_(this) {
[email protected]44ecb832013-08-02 09:06:45122 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
123}
124
[email protected]29998f92014-06-15 03:12:14125MidiPermissionContext::~MidiPermissionContext() {
[email protected]44ecb832013-08-02 09:06:45126 DCHECK(!permission_queue_controller_);
[email protected]1b6a1c22014-05-27 23:23:14127 DCHECK(pending_requests_.empty());
[email protected]44ecb832013-08-02 09:06:45128 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
129}
130
[email protected]29998f92014-06-15 03:12:14131void MidiPermissionContext::Shutdown() {
[email protected]44ecb832013-08-02 09:06:45132 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
133 permission_queue_controller_.reset();
134 shutting_down_ = true;
135}
136
[email protected]29998f92014-06-15 03:12:14137void MidiPermissionContext::RequestMidiSysExPermission(
138 content::WebContents* web_contents,
[email protected]00880a02013-10-30 03:18:30139 int bridge_id,
[email protected]44ecb832013-08-02 09:06:45140 const GURL& requesting_frame,
[email protected]7c6d9482014-03-28 20:19:31141 bool user_gesture,
[email protected]29998f92014-06-15 03:12:14142 const base::Callback<void(bool)>& result_callback,
143 base::Closure* cancel_callback) {
[email protected]44ecb832013-08-02 09:06:45144 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
145 DCHECK(!shutting_down_);
146
147 // TODO(toyoshim): Support Extension's manifest declared permission.
[email protected]6e068ea2014-02-04 07:05:47148 // See http://crbug.com/266338.
[email protected]44ecb832013-08-02 09:06:45149
[email protected]29998f92014-06-15 03:12:14150 int render_process_id = web_contents->GetRenderProcessHost()->GetID();
151 int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
152 if (cancel_callback) {
153 *cancel_callback = base::Bind(
154 &MidiPermissionContext::CancelMidiSysExPermissionRequest,
155 weak_factory_.GetWeakPtr(), render_process_id, render_view_id,
156 bridge_id);
157 }
[email protected]44ecb832013-08-02 09:06:45158
[email protected]5e170a52014-05-29 03:09:02159 const PermissionRequestID id(
160 render_process_id, render_view_id, bridge_id, GURL());
[email protected]44ecb832013-08-02 09:06:45161
162 GURL embedder = web_contents->GetURL();
[email protected]7ac9d812014-01-09 08:07:21163 // |requesting_frame| can be empty and invalid when the frame is a local
164 // file. Here local files should be granted to show an infobar.
165 // Any user's action will not be stored to content settings data base.
166 if ((!requesting_frame.is_valid() && !requesting_frame.is_empty()) ||
167 !embedder.is_valid()) {
[email protected]44ecb832013-08-02 09:06:45168 LOG(WARNING) << "Attempt to use MIDI sysex from an invalid URL: "
169 << requesting_frame << "," << embedder
170 << " (Web MIDI is not supported in popups)";
[email protected]29998f92014-06-15 03:12:14171 PermissionDecided(id, requesting_frame, embedder, result_callback, false);
[email protected]44ecb832013-08-02 09:06:45172 return;
173 }
174
[email protected]7c6d9482014-03-28 20:19:31175 DecidePermission(web_contents, id, requesting_frame, embedder, user_gesture,
[email protected]29998f92014-06-15 03:12:14176 result_callback);
[email protected]44ecb832013-08-02 09:06:45177}
178
[email protected]29998f92014-06-15 03:12:14179void MidiPermissionContext::CancelMidiSysExPermissionRequest(
[email protected]00880a02013-10-30 03:18:30180 int render_process_id,
181 int render_view_id,
[email protected]29998f92014-06-15 03:12:14182 int bridge_id) {
[email protected]566755f82014-01-08 01:14:57183 CancelPendingInfobarRequest(
[email protected]5e170a52014-05-29 03:09:02184 PermissionRequestID(
185 render_process_id, render_view_id, bridge_id, GURL()));
[email protected]00880a02013-10-30 03:18:30186}
187
[email protected]29998f92014-06-15 03:12:14188void MidiPermissionContext::DecidePermission(
[email protected]7babfcbe2014-02-12 22:56:38189 content::WebContents* web_contents,
[email protected]44ecb832013-08-02 09:06:45190 const PermissionRequestID& id,
191 const GURL& requesting_frame,
192 const GURL& embedder,
[email protected]7c6d9482014-03-28 20:19:31193 bool user_gesture,
[email protected]29998f92014-06-15 03:12:14194 const base::Callback<void(bool)>& callback) {
[email protected]44ecb832013-08-02 09:06:45195 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
196
197 ContentSetting content_setting =
198 profile_->GetHostContentSettingsMap()->GetContentSetting(
199 requesting_frame,
200 embedder,
201 CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
202 std::string());
203 switch (content_setting) {
204 case CONTENT_SETTING_BLOCK:
205 PermissionDecided(id, requesting_frame, embedder, callback, false);
206 break;
207 case CONTENT_SETTING_ALLOW:
208 PermissionDecided(id, requesting_frame, embedder, callback, true);
209 break;
210 default:
[email protected]7babfcbe2014-02-12 22:56:38211 if (PermissionBubbleManager::Enabled()) {
212 PermissionBubbleManager* bubble_manager =
213 PermissionBubbleManager::FromWebContents(web_contents);
[email protected]f2d770862014-05-13 03:26:14214 if (bubble_manager) {
[email protected]1b6a1c22014-05-27 23:23:14215 scoped_ptr<MidiPermissionRequest> request_ptr(
216 new MidiPermissionRequest(
217 this, id, requesting_frame, user_gesture,
218 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
219 callback));
220 MidiPermissionRequest* request = request_ptr.get();
221 bool inserted = pending_requests_.add(
222 id.ToString(), request_ptr.Pass()).second;
223 DCHECK(inserted) << "Duplicate id " << id.ToString();
224 bubble_manager->AddRequest(request);
[email protected]f2d770862014-05-13 03:26:14225 }
[email protected]7babfcbe2014-02-12 22:56:38226 return;
227 }
228
229 // TODO(gbillock): Delete this and the infobar delegate when
230 // we're using only bubbles. crbug.com/337458
[email protected]44ecb832013-08-02 09:06:45231 GetQueueController()->CreateInfoBarRequest(
[email protected]cc19a3262014-02-27 13:02:59232 id, requesting_frame, embedder, std::string(), base::Bind(
[email protected]29998f92014-06-15 03:12:14233 &MidiPermissionContext::NotifyPermissionSet,
[email protected]44ecb832013-08-02 09:06:45234 base::Unretained(this), id, requesting_frame, callback));
235 }
236}
237
[email protected]29998f92014-06-15 03:12:14238void MidiPermissionContext::PermissionDecided(
[email protected]44ecb832013-08-02 09:06:45239 const PermissionRequestID& id,
240 const GURL& requesting_frame,
241 const GURL& embedder,
[email protected]29998f92014-06-15 03:12:14242 const base::Callback<void(bool)>& callback,
[email protected]44ecb832013-08-02 09:06:45243 bool allowed) {
244 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
245 NotifyPermissionSet(id, requesting_frame, callback, allowed);
246}
247
[email protected]29998f92014-06-15 03:12:14248void MidiPermissionContext::NotifyPermissionSet(
[email protected]44ecb832013-08-02 09:06:45249 const PermissionRequestID& id,
250 const GURL& requesting_frame,
[email protected]29998f92014-06-15 03:12:14251 const base::Callback<void(bool)>& callback,
[email protected]44ecb832013-08-02 09:06:45252 bool allowed) {
253 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
254
255 TabSpecificContentSettings* content_settings =
256 TabSpecificContentSettings::Get(id.render_process_id(),
257 id.render_view_id());
258 if (content_settings) {
259 if (allowed)
[email protected]6e068ea2014-02-04 07:05:47260 content_settings->OnMidiSysExAccessed(requesting_frame);
[email protected]44ecb832013-08-02 09:06:45261 else
[email protected]6e068ea2014-02-04 07:05:47262 content_settings->OnMidiSysExAccessBlocked(requesting_frame);
[email protected]44ecb832013-08-02 09:06:45263 }
264
265 callback.Run(allowed);
266}
267
[email protected]29998f92014-06-15 03:12:14268PermissionQueueController* MidiPermissionContext::GetQueueController() {
[email protected]44ecb832013-08-02 09:06:45269 if (!permission_queue_controller_) {
270 permission_queue_controller_.reset(
271 new PermissionQueueController(profile_,
272 CONTENT_SETTINGS_TYPE_MIDI_SYSEX));
273 }
274 return permission_queue_controller_.get();
275}
[email protected]00880a02013-10-30 03:18:30276
[email protected]29998f92014-06-15 03:12:14277void MidiPermissionContext::RequestFinished(
[email protected]1b6a1c22014-05-27 23:23:14278 MidiPermissionRequest* request) {
279 base::ScopedPtrHashMap<std::string, MidiPermissionRequest>::iterator it;
280 for (it = pending_requests_.begin(); it != pending_requests_.end(); it++) {
281 if (it->second == request) {
282 pending_requests_.take_and_erase(it);
283 return;
284 }
285 }
286
287 NOTREACHED() << "Missing request";
288}
289
[email protected]29998f92014-06-15 03:12:14290void MidiPermissionContext::CancelPendingInfobarRequest(
[email protected]00880a02013-10-30 03:18:30291 const PermissionRequestID& id) {
292 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
293 if (shutting_down_)
294 return;
[email protected]1b6a1c22014-05-27 23:23:14295
296 if (PermissionBubbleManager::Enabled()) {
297 MidiPermissionRequest* cancelling = pending_requests_.get(id.ToString());
298 content::WebContents* web_contents = tab_util::GetWebContentsByID(
299 id.render_process_id(), id.render_view_id());
300 if (cancelling != NULL && web_contents != NULL &&
301 PermissionBubbleManager::FromWebContents(web_contents) != NULL) {
302 PermissionBubbleManager::FromWebContents(web_contents)->
303 CancelRequest(cancelling);
304 }
305 return;
306 }
307
[email protected]00880a02013-10-30 03:18:30308 GetQueueController()->CancelInfoBarRequest(id);
309}