| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright (c) 2012 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  | 
 |    5 #include "chrome/browser/media/media_stream_devices_controller.h" | 
 |    6  | 
 |    7 #include "base/values.h" | 
 |    8 #include "chrome/browser/content_settings/content_settings_provider.h" | 
 |    9 #include "chrome/browser/content_settings/host_content_settings_map.h" | 
 |   10 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 
 |   11 #include "chrome/browser/profiles/profile.h" | 
 |   12 #include "chrome/browser/ui/browser.h" | 
 |   13 #include "chrome/common/content_settings.h" | 
 |   14 #include "chrome/common/pref_names.h" | 
 |   15  | 
 |   16 using content::BrowserThread; | 
 |   17  | 
 |   18 namespace { | 
 |   19  | 
 |   20 // A predicate that checks if a StreamDeviceInfo object has the same ID as the | 
 |   21 // device ID specified at construction. | 
 |   22 class DeviceIdEquals { | 
 |   23  public: | 
 |   24   explicit DeviceIdEquals(const std::string& device_id) | 
 |   25       : device_id_(device_id) { | 
 |   26   } | 
 |   27  | 
 |   28   bool operator() (const content::MediaStreamDevice& device) { | 
 |   29     return device.device_id == device_id_; | 
 |   30   } | 
 |   31  | 
 |   32  private: | 
 |   33   std::string device_id_; | 
 |   34 }; | 
 |   35  | 
 |   36 // A predicate that checks if a StreamDeviceInfo object has the same device | 
 |   37 // name as the device name specified at construction. | 
 |   38 class DeviceNameEquals { | 
 |   39  public: | 
 |   40   explicit DeviceNameEquals(const std::string& device_name) | 
 |   41       : device_name_(device_name) { | 
 |   42   } | 
 |   43  | 
 |   44   bool operator() (const content::MediaStreamDevice& device) { | 
 |   45     return device.name == device_name_; | 
 |   46   } | 
 |   47  | 
 |   48  private: | 
 |   49   std::string device_name_; | 
 |   50 }; | 
 |   51  | 
 |   52 const char kAudioKey[] = "audio"; | 
 |   53 const char kVideoKey[] = "video"; | 
 |   54  | 
 |   55 }  // namespace | 
 |   56  | 
 |   57 MediaStreamDevicesController::MediaStreamDevicesController( | 
 |   58     Profile* profile, | 
 |   59     const content::MediaStreamRequest* request, | 
 |   60     const content::MediaResponseCallback& callback) | 
 |   61     : profile_(profile), | 
 |   62       request_(request), | 
 |   63       callback_(callback) { | 
 |   64   DCHECK(request_); | 
 |   65   has_audio_ = request_->devices.count( | 
 |   66       content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) != 0; | 
 |   67   has_video_ = request_->devices.count( | 
 |   68       content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) != 0; | 
 |   69 } | 
 |   70  | 
 |   71 MediaStreamDevicesController::~MediaStreamDevicesController() {} | 
 |   72  | 
 |   73 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() { | 
 |   74   // Deny the request if the security origin is empty, this happens with | 
 |   75   // file access without |--allow-file-access-from-files| flag. | 
 |   76   if (request_->security_origin.is_empty()) { | 
 |   77     Deny(); | 
 |   78     return true; | 
 |   79   } | 
 |   80  | 
 |   81   // Deny the request and don't show the infobar if there is no devices. | 
 |   82   if (!has_audio_ && !has_video_) { | 
 |   83     // TODO(xians): We should detect this in a early state, and post a callback | 
 |   84     // to tell the users that no device is available. Remove the code and add | 
 |   85     // a DCHECK when this is done. | 
 |   86     Deny(); | 
 |   87     return true; | 
 |   88   } | 
 |   89  | 
 |   90   // Checks if any exception has been made for this request, get the "always | 
 |   91   // allowed" devices if they are available. | 
 |   92   std::string audio, video; | 
 |   93   GetAlwaysAllowedDevices(&audio, &video); | 
 |   94   if ((has_audio_ && audio.empty()) || (has_video_ && video.empty())) { | 
 |   95     // If there is no "always allowed" device for the origin, or the device is | 
 |   96     // not available in the device lists, Check the default setting to see if | 
 |   97     // the user has blocked the access to the media device. | 
 |   98     if (IsMediaDeviceBlocked()) { | 
 |   99       Deny(); | 
 |  100       return true; | 
 |  101     } | 
 |  102  | 
 |  103     // Show the infobar. | 
 |  104     return false; | 
 |  105   } | 
 |  106  | 
 |  107   // Dismiss the infobar by selecting the "always allowed" devices. | 
 |  108   Accept(audio, video, false); | 
 |  109   return true; | 
 |  110 } | 
 |  111  | 
 |  112 content::MediaStreamDevices | 
 |  113 MediaStreamDevicesController::GetAudioDevices() const { | 
 |  114   if (!has_audio_) | 
 |  115     return content::MediaStreamDevices(); | 
 |  116  | 
 |  117   content::MediaStreamDeviceMap::const_iterator it = | 
 |  118       request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE); | 
 |  119   DCHECK(it != request_->devices.end()); | 
 |  120   return it->second; | 
 |  121 } | 
 |  122  | 
 |  123 content::MediaStreamDevices | 
 |  124 MediaStreamDevicesController::GetVideoDevices() const { | 
 |  125   if (!has_video_) | 
 |  126     return content::MediaStreamDevices(); | 
 |  127  | 
 |  128   content::MediaStreamDeviceMap::const_iterator it = | 
 |  129       request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); | 
 |  130   DCHECK(it != request_->devices.end()); | 
 |  131   return it->second; | 
 |  132 } | 
 |  133  | 
 |  134 const GURL& MediaStreamDevicesController::GetSecurityOrigin() const { | 
 |  135   return request_->security_origin; | 
 |  136 } | 
 |  137  | 
 |  138 void MediaStreamDevicesController::Accept(const std::string& audio_id, | 
 |  139                                           const std::string& video_id, | 
 |  140                                           bool always_allow) { | 
 |  141   content::MediaStreamDevices devices; | 
 |  142   std::string audio_device, video_device; | 
 |  143   if (has_audio_) { | 
 |  144     AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, | 
 |  145                     audio_id, &devices, &audio_device); | 
 |  146   } | 
 |  147   if (has_video_) { | 
 |  148     AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, | 
 |  149                     video_id, &devices, &video_device); | 
 |  150   } | 
 |  151   DCHECK(!devices.empty()); | 
 |  152  | 
 |  153   if (always_allow) | 
 |  154     AlwaysAllowOriginAndDevices(audio_device, video_device); | 
 |  155  | 
 |  156   callback_.Run(devices); | 
 |  157 } | 
 |  158  | 
 |  159 void MediaStreamDevicesController::Deny() { | 
 |  160   callback_.Run(content::MediaStreamDevices()); | 
 |  161 } | 
 |  162  | 
 |  163 void MediaStreamDevicesController::AddDeviceWithId( | 
 |  164     content::MediaStreamDeviceType type, | 
 |  165     const std::string& id, | 
 |  166     content::MediaStreamDevices* devices, | 
 |  167     std::string* device_name) { | 
 |  168   DCHECK(devices); | 
 |  169   content::MediaStreamDeviceMap::const_iterator device_it = | 
 |  170       request_->devices.find(type); | 
 |  171   if (device_it == request_->devices.end()) | 
 |  172     return; | 
 |  173  | 
 |  174   content::MediaStreamDevices::const_iterator it = std::find_if( | 
 |  175       device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id)); | 
 |  176   if (it == device_it->second.end()) | 
 |  177     return; | 
 |  178  | 
 |  179   devices->push_back(*it); | 
 |  180   *device_name = it->name; | 
 |  181 } | 
 |  182  | 
 |  183 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() { | 
 |  184   return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent( | 
 |  185       request_->security_origin, request_->security_origin, | 
 |  186       CONTENT_SETTINGS_TYPE_MEDIASTREAM); | 
 |  187 } | 
 |  188  | 
 |  189 bool MediaStreamDevicesController::IsMediaDeviceBlocked() { | 
 |  190   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
 |  191   ContentSetting current_setting = | 
 |  192       profile_->GetHostContentSettingsMap()->GetDefaultContentSetting( | 
 |  193           CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL); | 
 |  194   return (current_setting == CONTENT_SETTING_BLOCK); | 
 |  195 } | 
 |  196  | 
 |  197 void MediaStreamDevicesController::AlwaysAllowOriginAndDevices( | 
 |  198     const std::string& audio_device, | 
 |  199     const std::string& video_device) { | 
 |  200   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
 |  201   DCHECK(!audio_device.empty() || !video_device.empty()); | 
 |  202   DictionaryValue* dictionary_value = new DictionaryValue(); | 
 |  203   if (!audio_device.empty()) | 
 |  204     dictionary_value->SetString(kAudioKey, audio_device); | 
 |  205  | 
 |  206   if (!video_device.empty()) | 
 |  207     dictionary_value->SetString(kVideoKey, video_device); | 
 |  208  | 
 |  209   ContentSettingsPattern primary_pattern = | 
 |  210       ContentSettingsPattern::FromURLNoWildcard(request_->security_origin); | 
 |  211   profile_->GetHostContentSettingsMap()->SetWebsiteSetting( | 
 |  212       primary_pattern, | 
 |  213       ContentSettingsPattern::Wildcard(), | 
 |  214       CONTENT_SETTINGS_TYPE_MEDIASTREAM, | 
 |  215       NO_RESOURCE_IDENTIFIER, | 
 |  216       dictionary_value); | 
 |  217 } | 
 |  218  | 
 |  219 void MediaStreamDevicesController::GetAlwaysAllowedDevices( | 
 |  220     std::string* audio_id, std::string* video_id) { | 
 |  221   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
 |  222   DCHECK(audio_id->empty()); | 
 |  223   DCHECK(video_id->empty()); | 
 |  224   // If the request is from internal objects like chrome://URLs, use the first | 
 |  225   // devices on the lists. | 
 |  226   if (ShouldAlwaysAllowOrigin()) { | 
 |  227     if (has_audio_) { | 
 |  228       *audio_id = | 
 |  229           GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE); | 
 |  230     } | 
 |  231     if (has_video_) { | 
 |  232       *video_id = | 
 |  233           GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); | 
 |  234     } | 
 |  235     return; | 
 |  236   } | 
 |  237  | 
 |  238   // Checks the media exceptions to get the "always allowed" devices. | 
 |  239   scoped_ptr<Value> value( | 
 |  240       profile_->GetHostContentSettingsMap()->GetWebsiteSetting( | 
 |  241           request_->security_origin, | 
 |  242           request_->security_origin, | 
 |  243           CONTENT_SETTINGS_TYPE_MEDIASTREAM, | 
 |  244           NO_RESOURCE_IDENTIFIER, | 
 |  245           NULL)); | 
 |  246   if (!value.get()) { | 
 |  247     NOTREACHED(); | 
 |  248     return; | 
 |  249   } | 
 |  250  | 
 |  251   const DictionaryValue* value_dict = NULL; | 
 |  252   if (!value->GetAsDictionary(&value_dict) || value_dict->empty()) | 
 |  253     return; | 
 |  254  | 
 |  255   std::string audio_name, video_name; | 
 |  256   value_dict->GetString(kAudioKey, &audio_name); | 
 |  257   value_dict->GetString(kVideoKey, &video_name); | 
 |  258  | 
 |  259   if (has_audio_ && !audio_name.empty()) { | 
 |  260     *audio_id = GetDeviceIdByName( | 
 |  261         content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, audio_name); | 
 |  262   } | 
 |  263   if (has_video_ && !video_name.empty()) { | 
 |  264     *video_id = GetDeviceIdByName( | 
 |  265         content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, video_name); | 
 |  266   } | 
 |  267 } | 
 |  268  | 
 |  269 std::string MediaStreamDevicesController::GetDeviceIdByName( | 
 |  270     content::MediaStreamDeviceType type, | 
 |  271     const std::string& name) { | 
 |  272   content::MediaStreamDeviceMap::const_iterator device_it = | 
 |  273       request_->devices.find(type); | 
 |  274   if (device_it != request_->devices.end()) { | 
 |  275     content::MediaStreamDevices::const_iterator it = std::find_if( | 
 |  276         device_it->second.begin(), device_it->second.end(), | 
 |  277         DeviceNameEquals(name)); | 
 |  278     if (it != device_it->second.end()) | 
 |  279       return it->device_id; | 
 |  280   } | 
 |  281  | 
 |  282   // Device is not available, return an empty string. | 
 |  283   return std::string(); | 
 |  284 } | 
 |  285  | 
 |  286 std::string MediaStreamDevicesController::GetFirstDeviceId( | 
 |  287     content::MediaStreamDeviceType type) { | 
 |  288   content::MediaStreamDeviceMap::const_iterator device_it = | 
 |  289       request_->devices.find(type); | 
 |  290   if (device_it != request_->devices.end()) | 
 |  291     return device_it->second.begin()->device_id; | 
 |  292  | 
 |  293   return std::string(); | 
 |  294 } | 
| OLD | NEW |