OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/media/midi_permission_context.h" | 5 #include "chrome/browser/media/midi_permission_context.h" |
6 | 6 |
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" | 7 #include "chrome/browser/content_settings/permission_request_id.h" |
11 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 8 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
12 #include "chrome/browser/profiles/profile.h" | 9 #include "url/gurl.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/render_process_host.h" | |
19 #include "content/public/browser/render_view_host.h" | |
20 #include "content/public/browser/web_contents.h" | |
21 #include "grit/generated_resources.h" | |
22 #include "grit/theme_resources.h" | |
23 #include "net/base/net_util.h" | |
24 #include "ui/base/l10n/l10n_util.h" | |
25 | |
26 class MidiPermissionRequest : public PermissionBubbleRequest { | |
27 public: | |
28 MidiPermissionRequest( | |
29 MidiPermissionContext* context, | |
30 const PermissionRequestID& id, | |
31 const GURL& requesting_frame, | |
32 bool user_gesture, | |
33 const std::string& display_languages, | |
34 const base::Callback<void(bool)>& callback); | |
35 virtual ~MidiPermissionRequest(); | |
36 | |
37 // PermissionBubbleDelegate: | |
38 virtual int GetIconID() const OVERRIDE; | |
39 virtual base::string16 GetMessageText() const OVERRIDE; | |
40 virtual base::string16 GetMessageTextFragment() const OVERRIDE; | |
41 virtual bool HasUserGesture() const OVERRIDE; | |
42 virtual GURL GetRequestingHostname() const OVERRIDE; | |
43 virtual void PermissionGranted() OVERRIDE; | |
44 virtual void PermissionDenied() OVERRIDE; | |
45 virtual void Cancelled() OVERRIDE; | |
46 virtual void RequestFinished() OVERRIDE; | |
47 | |
48 private: | |
49 MidiPermissionContext* context_; | |
50 const PermissionRequestID id_; | |
51 GURL requesting_frame_; | |
52 bool user_gesture_; | |
53 std::string display_languages_; | |
54 const base::Callback<void(bool)>& callback_; | |
55 bool is_finished_; | |
56 | |
57 DISALLOW_COPY_AND_ASSIGN(MidiPermissionRequest); | |
58 }; | |
59 | |
60 MidiPermissionRequest::MidiPermissionRequest( | |
61 MidiPermissionContext* context, | |
62 const PermissionRequestID& id, | |
63 const GURL& requesting_frame, | |
64 bool user_gesture, | |
65 const std::string& display_languages, | |
66 const base::Callback<void(bool)>& callback) | |
67 : context_(context), | |
68 id_(id), | |
69 requesting_frame_(requesting_frame), | |
70 user_gesture_(user_gesture), | |
71 display_languages_(display_languages), | |
72 callback_(callback), | |
73 is_finished_(false) {} | |
74 | |
75 MidiPermissionRequest::~MidiPermissionRequest() { | |
76 DCHECK(is_finished_); | |
77 } | |
78 | |
79 int MidiPermissionRequest::GetIconID() const { | |
80 return IDR_ALLOWED_MIDI_SYSEX; | |
81 } | |
82 | |
83 base::string16 MidiPermissionRequest::GetMessageText() const { | |
84 return l10n_util::GetStringFUTF16( | |
85 IDS_MIDI_SYSEX_INFOBAR_QUESTION, | |
86 net::FormatUrl(requesting_frame_.GetOrigin(), display_languages_, | |
87 net::kFormatUrlOmitUsernamePassword | | |
88 net::kFormatUrlOmitTrailingSlashOnBareHostname, | |
89 net::UnescapeRule::SPACES, NULL, NULL, NULL)); | |
90 } | |
91 | |
92 base::string16 MidiPermissionRequest::GetMessageTextFragment() const { | |
93 return l10n_util::GetStringUTF16(IDS_MIDI_SYSEX_PERMISSION_FRAGMENT); | |
94 } | |
95 | |
96 bool MidiPermissionRequest::HasUserGesture() const { | |
97 return user_gesture_; | |
98 } | |
99 | |
100 GURL MidiPermissionRequest::GetRequestingHostname() const { | |
101 return requesting_frame_; | |
102 } | |
103 | |
104 void MidiPermissionRequest::PermissionGranted() { | |
105 context_->NotifyPermissionSet(id_, requesting_frame_, callback_, true); | |
106 } | |
107 | |
108 void MidiPermissionRequest::PermissionDenied() { | |
109 context_->NotifyPermissionSet(id_, requesting_frame_, callback_, false); | |
110 } | |
111 | |
112 void MidiPermissionRequest::Cancelled() { | |
113 } | |
114 | |
115 void MidiPermissionRequest::RequestFinished() { | |
116 is_finished_ = true; | |
117 // Deletes 'this'. | |
118 context_->RequestFinished(this); | |
119 } | |
120 | 10 |
121 MidiPermissionContext::MidiPermissionContext(Profile* profile) | 11 MidiPermissionContext::MidiPermissionContext(Profile* profile) |
122 : profile_(profile), | 12 : PermissionContextBase(profile, CONTENT_SETTINGS_TYPE_MIDI_SYSEX){ |
123 shutting_down_(false), | |
124 weak_factory_(this) { | |
125 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
126 } | 13 } |
127 | 14 |
128 MidiPermissionContext::~MidiPermissionContext() { | 15 MidiPermissionContext::~MidiPermissionContext() { |
129 DCHECK(!permission_queue_controller_); | |
130 DCHECK(pending_requests_.empty()); | |
131 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
132 } | 16 } |
133 | 17 |
134 void MidiPermissionContext::Shutdown() { | |
135 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
136 permission_queue_controller_.reset(); | |
137 shutting_down_ = true; | |
138 } | |
139 | 18 |
140 void MidiPermissionContext::RequestMidiSysExPermission( | 19 void MidiPermissionContext::UpdateTabContext(const PermissionRequestID& id, |
141 content::WebContents* web_contents, | 20 const GURL& requesting_frame, |
142 int bridge_id, | 21 bool allowed) { |
143 const GURL& requesting_frame, | |
144 bool user_gesture, | |
145 const base::Callback<void(bool)>& result_callback, | |
146 base::Closure* cancel_callback) { | |
147 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
148 DCHECK(!shutting_down_); | |
149 | |
150 // TODO(toyoshim): Support Extension's manifest declared permission. | |
151 // See http://crbug.com/266338. | |
152 | |
153 int render_process_id = web_contents->GetRenderProcessHost()->GetID(); | |
154 int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID(); | |
155 if (cancel_callback) { | |
156 *cancel_callback = base::Bind( | |
157 &MidiPermissionContext::CancelMidiSysExPermissionRequest, | |
158 weak_factory_.GetWeakPtr(), render_process_id, render_view_id, | |
159 bridge_id); | |
160 } | |
161 | |
162 const PermissionRequestID id( | |
163 render_process_id, render_view_id, bridge_id, GURL()); | |
164 | |
165 GURL embedder = web_contents->GetURL(); | |
166 // |requesting_frame| can be empty and invalid when the frame is a local | |
167 // file. Here local files should be granted to show an infobar. | |
168 // Any user's action will not be stored to content settings data base. | |
169 if ((!requesting_frame.is_valid() && !requesting_frame.is_empty()) || | |
170 !embedder.is_valid()) { | |
171 LOG(WARNING) << "Attempt to use MIDI sysex from an invalid URL: " | |
172 << requesting_frame << "," << embedder | |
173 << " (Web MIDI is not supported in popups)"; | |
174 PermissionDecided(id, requesting_frame, embedder, result_callback, false); | |
175 return; | |
176 } | |
177 | |
178 DecidePermission(web_contents, id, requesting_frame, embedder, user_gesture, | |
179 result_callback); | |
180 } | |
181 | |
182 void MidiPermissionContext::CancelMidiSysExPermissionRequest( | |
183 int render_process_id, | |
184 int render_view_id, | |
185 int bridge_id) { | |
186 CancelPendingInfobarRequest( | |
187 PermissionRequestID( | |
188 render_process_id, render_view_id, bridge_id, GURL())); | |
189 } | |
190 | |
191 void MidiPermissionContext::DecidePermission( | |
192 content::WebContents* web_contents, | |
193 const PermissionRequestID& id, | |
194 const GURL& requesting_frame, | |
195 const GURL& embedder, | |
196 bool user_gesture, | |
197 const base::Callback<void(bool)>& callback) { | |
198 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
199 | |
200 ContentSetting content_setting = | |
201 profile_->GetHostContentSettingsMap()->GetContentSetting( | |
202 requesting_frame, | |
203 embedder, | |
204 CONTENT_SETTINGS_TYPE_MIDI_SYSEX, | |
205 std::string()); | |
206 switch (content_setting) { | |
207 case CONTENT_SETTING_BLOCK: | |
208 PermissionDecided(id, requesting_frame, embedder, callback, false); | |
209 break; | |
210 case CONTENT_SETTING_ALLOW: | |
211 PermissionDecided(id, requesting_frame, embedder, callback, true); | |
212 break; | |
213 default: | |
214 if (PermissionBubbleManager::Enabled()) { | |
215 PermissionBubbleManager* bubble_manager = | |
216 PermissionBubbleManager::FromWebContents(web_contents); | |
217 if (bubble_manager) { | |
218 scoped_ptr<MidiPermissionRequest> request_ptr( | |
219 new MidiPermissionRequest( | |
220 this, id, requesting_frame, user_gesture, | |
221 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages), | |
222 callback)); | |
223 MidiPermissionRequest* request = request_ptr.get(); | |
224 bool inserted = pending_requests_.add( | |
225 id.ToString(), request_ptr.Pass()).second; | |
226 DCHECK(inserted) << "Duplicate id " << id.ToString(); | |
227 bubble_manager->AddRequest(request); | |
228 } | |
229 return; | |
230 } | |
231 | |
232 // TODO(gbillock): Delete this and the infobar delegate when | |
233 // we're using only bubbles. crbug.com/337458 | |
234 GetQueueController()->CreateInfoBarRequest( | |
235 id, requesting_frame, embedder, std::string(), base::Bind( | |
236 &MidiPermissionContext::NotifyPermissionSet, | |
237 base::Unretained(this), id, requesting_frame, callback)); | |
238 } | |
239 } | |
240 | |
241 void MidiPermissionContext::PermissionDecided( | |
242 const PermissionRequestID& id, | |
243 const GURL& requesting_frame, | |
244 const GURL& embedder, | |
245 const base::Callback<void(bool)>& callback, | |
246 bool allowed) { | |
247 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
248 NotifyPermissionSet(id, requesting_frame, callback, allowed); | |
249 } | |
250 | |
251 void MidiPermissionContext::NotifyPermissionSet( | |
252 const PermissionRequestID& id, | |
253 const GURL& requesting_frame, | |
254 const base::Callback<void(bool)>& callback, | |
255 bool allowed) { | |
256 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
257 | |
258 TabSpecificContentSettings* content_settings = | 22 TabSpecificContentSettings* content_settings = |
259 TabSpecificContentSettings::Get(id.render_process_id(), | 23 TabSpecificContentSettings::Get(id.render_process_id(), |
260 id.render_view_id()); | 24 id.render_view_id()); |
261 if (content_settings) { | 25 if (content_settings) { |
262 if (allowed) | 26 if (allowed) |
263 content_settings->OnMidiSysExAccessed(requesting_frame); | 27 content_settings->OnMidiSysExAccessed(requesting_frame); |
264 else | 28 else |
265 content_settings->OnMidiSysExAccessBlocked(requesting_frame); | 29 content_settings->OnMidiSysExAccessBlocked(requesting_frame); |
266 } | 30 } |
267 | |
268 callback.Run(allowed); | |
269 } | 31 } |
270 | |
271 PermissionQueueController* MidiPermissionContext::GetQueueController() { | |
272 if (!permission_queue_controller_) { | |
273 permission_queue_controller_.reset( | |
274 new PermissionQueueController(profile_, | |
275 CONTENT_SETTINGS_TYPE_MIDI_SYSEX)); | |
276 } | |
277 return permission_queue_controller_.get(); | |
278 } | |
279 | |
280 void MidiPermissionContext::RequestFinished( | |
281 MidiPermissionRequest* request) { | |
282 base::ScopedPtrHashMap<std::string, MidiPermissionRequest>::iterator it; | |
283 for (it = pending_requests_.begin(); it != pending_requests_.end(); it++) { | |
284 if (it->second == request) { | |
285 pending_requests_.take_and_erase(it); | |
286 return; | |
287 } | |
288 } | |
289 | |
290 NOTREACHED() << "Missing request"; | |
291 } | |
292 | |
293 void MidiPermissionContext::CancelPendingInfobarRequest( | |
294 const PermissionRequestID& id) { | |
295 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
296 if (shutting_down_) | |
297 return; | |
298 | |
299 if (PermissionBubbleManager::Enabled()) { | |
300 MidiPermissionRequest* cancelling = pending_requests_.get(id.ToString()); | |
301 content::WebContents* web_contents = tab_util::GetWebContentsByID( | |
302 id.render_process_id(), id.render_view_id()); | |
303 if (cancelling != NULL && web_contents != NULL && | |
304 PermissionBubbleManager::FromWebContents(web_contents) != NULL) { | |
305 PermissionBubbleManager::FromWebContents(web_contents)-> | |
306 CancelRequest(cancelling); | |
307 } | |
308 return; | |
309 } | |
310 | |
311 GetQueueController()->CancelInfoBarRequest(id); | |
312 } | |
OLD | NEW |