1 // 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.
5 #include "chrome/browser/media/chrome_midi_permission_context.h"
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"
14 #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"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/web_contents.h"
19 #include "grit/generated_resources.h"
20 #include "grit/theme_resources.h"
21 #include "net/base/net_util.h"
22 #include "ui/base/l10n/l10n_util.h"
24 class MidiPermissionRequest
: public PermissionBubbleRequest
{
26 MidiPermissionRequest(
27 ChromeMidiPermissionContext
* context
,
28 const PermissionRequestID
& id
,
29 const GURL
& requesting_frame
,
31 const std::string
& display_languages
,
32 const content::BrowserContext::MidiSysExPermissionCallback
& callback
);
33 virtual ~MidiPermissionRequest();
35 // PermissionBubbleDelegate:
36 virtual int GetIconID() const OVERRIDE
;
37 virtual base::string16
GetMessageText() const OVERRIDE
;
38 virtual base::string16
GetMessageTextFragment() const OVERRIDE
;
39 virtual bool HasUserGesture() const OVERRIDE
;
40 virtual GURL
GetRequestingHostname() const OVERRIDE
;
41 virtual void PermissionGranted() OVERRIDE
;
42 virtual void PermissionDenied() OVERRIDE
;
43 virtual void Cancelled() OVERRIDE
;
44 virtual void RequestFinished() OVERRIDE
;
47 ChromeMidiPermissionContext
* context_
;
48 const PermissionRequestID id_
;
49 GURL requesting_frame_
;
51 std::string display_languages_
;
52 const content::BrowserContext::MidiSysExPermissionCallback
& callback_
;
54 DISALLOW_COPY_AND_ASSIGN(MidiPermissionRequest
);
57 MidiPermissionRequest::MidiPermissionRequest(
58 ChromeMidiPermissionContext
* context
,
59 const PermissionRequestID
& id
,
60 const GURL
& requesting_frame
,
62 const std::string
& display_languages
,
63 const content::BrowserContext::MidiSysExPermissionCallback
& callback
)
66 requesting_frame_(requesting_frame
),
67 user_gesture_(user_gesture
),
68 display_languages_(display_languages
),
69 callback_(callback
) {}
71 MidiPermissionRequest::~MidiPermissionRequest() {}
73 int MidiPermissionRequest::GetIconID() const {
74 return IDR_ALLOWED_MIDI_SYSEX
;
77 base::string16
MidiPermissionRequest::GetMessageText() const {
78 return l10n_util::GetStringFUTF16(
79 IDS_MIDI_SYSEX_INFOBAR_QUESTION
,
80 net::FormatUrl(requesting_frame_
.GetOrigin(), display_languages_
));
83 base::string16
MidiPermissionRequest::GetMessageTextFragment() const {
84 return l10n_util::GetStringUTF16(IDS_MIDI_SYSEX_PERMISSION_FRAGMENT
);
87 bool MidiPermissionRequest::HasUserGesture() const {
91 GURL
MidiPermissionRequest::GetRequestingHostname() const {
92 return requesting_frame_
;
95 void MidiPermissionRequest::PermissionGranted() {
96 context_
->NotifyPermissionSet(id_
, requesting_frame_
, callback_
, true);
99 void MidiPermissionRequest::PermissionDenied() {
100 context_
->NotifyPermissionSet(id_
, requesting_frame_
, callback_
, false);
103 void MidiPermissionRequest::Cancelled() {
104 context_
->NotifyPermissionSet(id_
, requesting_frame_
, callback_
, false);
107 void MidiPermissionRequest::RequestFinished() {
111 ChromeMidiPermissionContext::ChromeMidiPermissionContext(Profile
* profile
)
113 shutting_down_(false) {
114 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
117 ChromeMidiPermissionContext::~ChromeMidiPermissionContext() {
118 DCHECK(!permission_queue_controller_
);
119 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
122 void ChromeMidiPermissionContext::Shutdown() {
123 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
124 permission_queue_controller_
.reset();
125 shutting_down_
= true;
128 void ChromeMidiPermissionContext::RequestMidiSysExPermission(
129 int render_process_id
,
132 const GURL
& requesting_frame
,
134 const content::BrowserContext::MidiSysExPermissionCallback
& callback
) {
135 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
136 DCHECK(!shutting_down_
);
138 // TODO(toyoshim): Support Extension's manifest declared permission.
139 // See http://crbug.com/266338.
141 content::WebContents
* web_contents
=
142 tab_util::GetWebContentsByID(render_process_id
, render_view_id
);
144 // The page doesn't exist any more.
148 const PermissionRequestID
id(render_process_id
, render_view_id
, bridge_id
, 0);
150 GURL embedder
= web_contents
->GetURL();
151 // |requesting_frame| can be empty and invalid when the frame is a local
152 // file. Here local files should be granted to show an infobar.
153 // Any user's action will not be stored to content settings data base.
154 if ((!requesting_frame
.is_valid() && !requesting_frame
.is_empty()) ||
155 !embedder
.is_valid()) {
156 LOG(WARNING
) << "Attempt to use MIDI sysex from an invalid URL: "
157 << requesting_frame
<< "," << embedder
158 << " (Web MIDI is not supported in popups)";
159 PermissionDecided(id
, requesting_frame
, embedder
, callback
, false);
163 DecidePermission(web_contents
, id
, requesting_frame
, embedder
, user_gesture
,
167 void ChromeMidiPermissionContext::CancelMidiSysExPermissionRequest(
168 int render_process_id
,
171 const GURL
& requesting_frame
) {
172 CancelPendingInfobarRequest(
173 PermissionRequestID(render_process_id
, render_view_id
, bridge_id
, 0));
176 void ChromeMidiPermissionContext::DecidePermission(
177 content::WebContents
* web_contents
,
178 const PermissionRequestID
& id
,
179 const GURL
& requesting_frame
,
180 const GURL
& embedder
,
182 const content::BrowserContext::MidiSysExPermissionCallback
& callback
) {
183 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
185 ContentSetting content_setting
=
186 profile_
->GetHostContentSettingsMap()->GetContentSetting(
189 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
,
191 switch (content_setting
) {
192 case CONTENT_SETTING_BLOCK
:
193 PermissionDecided(id
, requesting_frame
, embedder
, callback
, false);
195 case CONTENT_SETTING_ALLOW
:
196 PermissionDecided(id
, requesting_frame
, embedder
, callback
, true);
199 if (PermissionBubbleManager::Enabled()) {
200 PermissionBubbleManager
* bubble_manager
=
201 PermissionBubbleManager::FromWebContents(web_contents
);
202 bubble_manager
->AddRequest(new MidiPermissionRequest(
203 this, id
, requesting_frame
, user_gesture
,
204 profile_
->GetPrefs()->GetString(prefs::kAcceptLanguages
),
209 // TODO(gbillock): Delete this and the infobar delegate when
210 // we're using only bubbles. crbug.com/337458
211 GetQueueController()->CreateInfoBarRequest(
212 id
, requesting_frame
, embedder
, std::string(), base::Bind(
213 &ChromeMidiPermissionContext::NotifyPermissionSet
,
214 base::Unretained(this), id
, requesting_frame
, callback
));
218 void ChromeMidiPermissionContext::PermissionDecided(
219 const PermissionRequestID
& id
,
220 const GURL
& requesting_frame
,
221 const GURL
& embedder
,
222 const content::BrowserContext::MidiSysExPermissionCallback
& callback
,
224 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
225 NotifyPermissionSet(id
, requesting_frame
, callback
, allowed
);
228 void ChromeMidiPermissionContext::NotifyPermissionSet(
229 const PermissionRequestID
& id
,
230 const GURL
& requesting_frame
,
231 const content::BrowserContext::MidiSysExPermissionCallback
& callback
,
233 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
235 TabSpecificContentSettings
* content_settings
=
236 TabSpecificContentSettings::Get(id
.render_process_id(),
237 id
.render_view_id());
238 if (content_settings
) {
240 content_settings
->OnMidiSysExAccessed(requesting_frame
);
242 content_settings
->OnMidiSysExAccessBlocked(requesting_frame
);
245 callback
.Run(allowed
);
248 PermissionQueueController
* ChromeMidiPermissionContext::GetQueueController() {
249 if (!permission_queue_controller_
) {
250 permission_queue_controller_
.reset(
251 new PermissionQueueController(profile_
,
252 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
));
254 return permission_queue_controller_
.get();
257 void ChromeMidiPermissionContext::CancelPendingInfobarRequest(
258 const PermissionRequestID
& id
) {
259 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
262 // TODO(gbillock): Add support for cancellation to permission bubbles.
263 GetQueueController()->CancelInfoBarRequest(id
);