| 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 |