summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd16
-rw-r--r--chrome/browser/chrome_content_browser_client.cc41
-rw-r--r--chrome/browser/infobars/infobar_delegate.cc4
-rw-r--r--chrome/browser/infobars/infobar_delegate.h2
-rw-r--r--chrome/browser/media/media_stream_devices_menu_model.cc87
-rw-r--r--chrome/browser/media/media_stream_devices_menu_model.h58
-rw-r--r--chrome/browser/ui/media_stream_infobar_delegate.cc140
-rw-r--r--chrome/browser/ui/media_stream_infobar_delegate.h82
-rw-r--r--chrome/browser/ui/views/infobars/media_stream_infobar.cc129
-rw-r--r--chrome/browser/ui/views/infobars/media_stream_infobar.h57
-rw-r--r--chrome/chrome_browser.gypi6
-rw-r--r--content/browser/renderer_host/media/media_stream_device_settings.cc6
-rw-r--r--content/browser/renderer_host/media/media_stream_device_settings.h2
-rw-r--r--content/public/browser/content_browser_client.h2
-rw-r--r--content/public/common/media_stream_request.h4
15 files changed, 616 insertions, 20 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 32fef50..a900770 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -15368,20 +15368,20 @@ Battery full
<message name="IDS_MEDIA_CAPTURE_VIDEO_ONLY" desc="Question asked on the info bar whenever a web page requests access to the computer's camera.">
<ph name="HOST">$1<ex>html5rocks.com</ex></ph> wants to use your camera.
</message>
- <message name="IDS_MEDIA_CAPTURE_MIC" desc="Label for a microphone list drop-down.">
- Microphone:
+ <message name="IDS_MEDIA_CAPTURE_MIC" desc="Label for a microphone element in a device list.">
+ Microphone: <ph name="DEVICE_NAME">$1<ex>default microphone</ex></ph>
</message>
- <message name="IDS_MEDIA_CAPTURE_VIDEO" desc="Label for a camera list drop-down.">
- Camera:
+ <message name="IDS_MEDIA_CAPTURE_VIDEO" desc="Label for a camera element in a device list.">
+ Camera: <ph name="DEVICE_NAME">$1<ex>Built-in camera</ex></ph>
</message>
- <message name="IDS_MEDIA_CAPTURE_ALLOW" desc="Label for a button that grants access to a web page, so they can use a camera and/or a microphone.">
+ <message name="IDS_MEDIA_CAPTURE_ALLOW" desc="Label for a button that grants access to a web page, so they can use a camera and/or a microphone.">
Allow
</message>
- <message name="IDS_MEDIA_CAPTURE_DENY" desc="Label for a button that denies access to a web page, so they can use a camera and/or a microphone.">
+ <message name="IDS_MEDIA_CAPTURE_DENY" desc="Label for a button that denies access to a web page, so they can use a camera and/or a microphone.">
Deny
</message>
- <message name="IDS_MEDIA_CAPTURE_NO_DEVICES" desc="Label for a drop-down button, used if there are no available devices (e.g. camera, microphone) available on the computer.">
- (no devices)
+ <message name="IDS_MEDIA_CAPTURE_DEVICES_MENU_TITLE" desc="Label for a drop-down menu button that will, when clicked, list the available and selected camera and/or microphone devices.">
+ Devices
</message>
<!-- Quota messages -->
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 5a898a9..32a58c3 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -35,6 +35,7 @@
#include "chrome/browser/extensions/extension_webkit_preferences.h"
#include "chrome/browser/geolocation/chrome_access_token_store.h"
#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/desktop_notification_service_factory.h"
@@ -58,6 +59,7 @@
#include "chrome/browser/ssl/ssl_blocking_page.h"
#include "chrome/browser/tab_contents/tab_contents_ssl_helper.h"
#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/browser/ui/media_stream_infobar_delegate.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
#include "chrome/browser/user_style_sheet_watcher.h"
@@ -1063,17 +1065,46 @@ void ChromeContentBrowserClient::RequestMediaAccessPermission(
const content::MediaResponseCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- content::MediaStreamDeviceArray devices;
+ WebContents* contents = tab_util::GetWebContentsByID(
+ request->render_process_id, request->render_view_id);
+ if (!contents) {
+ // Abort, if the tab was closed after the request was made but before we
+ // got to this point.
+ callback.Run(content::MediaStreamDevices());
+ return;
+ }
+
+ TabContentsWrapper* tab =
+ TabContentsWrapper::GetCurrentWrapperForContents(contents);
+ DCHECK(tab);
+
+ InfoBarTabHelper* infobar_helper = tab->infobar_tab_helper();
+ InfoBarDelegate* old_infobar = NULL;
+ for (size_t i = 0; i < infobar_helper->infobar_count() && !old_infobar; ++i) {
+ old_infobar =
+ infobar_helper->GetInfoBarDelegateAt(i)->AsMediaStreamInfobarDelegate();
+ }
+
+#if defined(TOOLKIT_VIEWS)
+ InfoBarDelegate* infobar = new MediaStreamInfoBarDelegate(infobar_helper,
+ request,
+ callback);
+ if (old_infobar)
+ infobar_helper->ReplaceInfoBar(old_infobar, infobar);
+ else
+ infobar_helper->AddInfoBar(infobar);
+#elif defined(OS_LINUX) || defined(OS_MACOSX)
+ // TODO(macourteau): UI is not implemented yet for Linux and OS X. Fallback to
+ // the default behaviour and allow access to the first device of each
+ // requested type.
+ content::MediaStreamDevices devices;
for (content::MediaStreamDeviceMap::const_iterator it =
request->devices.begin(); it != request->devices.end(); ++it) {
devices.push_back(*it->second.begin());
}
- // TODO(macourteau): This is temporary. The base::Callback object will be
- // passed to the Infobar, which will Run it with the request's label and the
- // list of accepted devices (if any), or an empty list of devices if the user
- // has denied the request.
callback.Run(devices);
+#endif // TOOLKIT_VIEWS
}
void ChromeContentBrowserClient::RequestDesktopNotificationPermission(
diff --git a/chrome/browser/infobars/infobar_delegate.cc b/chrome/browser/infobars/infobar_delegate.cc
index bcaf344..25a65ce 100644
--- a/chrome/browser/infobars/infobar_delegate.cc
+++ b/chrome/browser/infobars/infobar_delegate.cc
@@ -63,6 +63,10 @@ LinkInfoBarDelegate* InfoBarDelegate::AsLinkInfoBarDelegate() {
return NULL;
}
+MediaStreamInfoBarDelegate* InfoBarDelegate::AsMediaStreamInfobarDelegate() {
+ return NULL;
+}
+
RegisterProtocolHandlerInfoBarDelegate*
InfoBarDelegate::AsRegisterProtocolHandlerInfoBarDelegate() {
return NULL;
diff --git a/chrome/browser/infobars/infobar_delegate.h b/chrome/browser/infobars/infobar_delegate.h
index 785f67b..3dcda68 100644
--- a/chrome/browser/infobars/infobar_delegate.h
+++ b/chrome/browser/infobars/infobar_delegate.h
@@ -16,6 +16,7 @@ class InfoBar;
class InfoBarTabHelper;
class InsecureContentInfoBarDelegate;
class LinkInfoBarDelegate;
+class MediaStreamInfoBarDelegate;
class PluginInstallerInfoBarDelegate;
class RegisterProtocolHandlerInfoBarDelegate;
class ThemeInstalledInfoBarDelegate;
@@ -88,6 +89,7 @@ class InfoBarDelegate {
virtual ExtensionInfoBarDelegate* AsExtensionInfoBarDelegate();
virtual InsecureContentInfoBarDelegate* AsInsecureContentInfoBarDelegate();
virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate();
+ virtual MediaStreamInfoBarDelegate* AsMediaStreamInfobarDelegate();
virtual RegisterProtocolHandlerInfoBarDelegate*
AsRegisterProtocolHandlerInfoBarDelegate();
virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
diff --git a/chrome/browser/media/media_stream_devices_menu_model.cc b/chrome/browser/media/media_stream_devices_menu_model.cc
new file mode 100644
index 0000000..119d424
--- /dev/null
+++ b/chrome/browser/media/media_stream_devices_menu_model.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/media_stream_devices_menu_model.h"
+
+#include <utility>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/media_stream_infobar_delegate.h"
+#include "content/public/common/media_stream_request.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+MediaStreamDevicesMenuModel::MediaStreamDevicesMenuModel(
+ const MediaStreamInfoBarDelegate* delegate)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
+ selected_command_id_audio_(-1),
+ selected_command_id_video_(-1) {
+ const bool nonempty_audio_section =
+ delegate->has_audio() && !delegate->GetAudioDevices().empty();
+ if (delegate->has_video() && !delegate->GetVideoDevices().empty()) {
+ // The default command ID is the first element that will be inserted.
+ selected_command_id_video_ = commands_.size();
+ AddDevices(delegate->GetVideoDevices());
+ if (nonempty_audio_section)
+ AddSeparator();
+ }
+ if (nonempty_audio_section) {
+ // The default command ID is the first element that will be inserted.
+ selected_command_id_audio_ = commands_.size();
+ AddDevices(delegate->GetAudioDevices());
+ }
+}
+
+MediaStreamDevicesMenuModel::~MediaStreamDevicesMenuModel() {
+}
+
+void MediaStreamDevicesMenuModel::AddDevices(
+ const content::MediaStreamDevices& devices) {
+ for (size_t i = 0; i < devices.size(); ++i) {
+ int command_id = commands_.size();
+ commands_.insert(std::make_pair(command_id, devices[i]));
+ int message_id = (devices[i].type ==
+ content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) ?
+ IDS_MEDIA_CAPTURE_MIC : IDS_MEDIA_CAPTURE_VIDEO;
+ AddCheckItem(command_id,
+ l10n_util::GetStringFUTF16(message_id,
+ UTF8ToUTF16(devices[i].name)));
+ }
+}
+
+bool MediaStreamDevicesMenuModel::GetSelectedDeviceId(
+ content::MediaStreamDeviceType type,
+ std::string* device_id) const {
+ int command_id = (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) ?
+ selected_command_id_audio_ : selected_command_id_video_;
+ CommandMap::const_iterator it = commands_.find(command_id);
+ if (it != commands_.end())
+ *device_id = it->second.device_id;
+ return (it != commands_.end());
+}
+
+bool MediaStreamDevicesMenuModel::IsCommandIdChecked(int command_id) const {
+ return (selected_command_id_audio_ == command_id ||
+ selected_command_id_video_ == command_id);
+}
+
+bool MediaStreamDevicesMenuModel::IsCommandIdEnabled(int command_id) const {
+ return true;
+}
+
+bool MediaStreamDevicesMenuModel::GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) {
+ return false;
+}
+
+void MediaStreamDevicesMenuModel::ExecuteCommand(int command_id) {
+ CommandMap::iterator it = commands_.find(command_id);
+ DCHECK(it != commands_.end());
+
+ if (it->second.type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE)
+ selected_command_id_audio_ = command_id;
+ else
+ selected_command_id_video_ = command_id;
+}
diff --git a/chrome/browser/media/media_stream_devices_menu_model.h b/chrome/browser/media/media_stream_devices_menu_model.h
new file mode 100644
index 0000000..fa22ae0
--- /dev/null
+++ b/chrome/browser/media/media_stream_devices_menu_model.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_MEDIA_STREAM_DEVICES_MENU_MODEL_H_
+#define CHROME_BROWSER_MEDIA_MEDIA_STREAM_DEVICES_MENU_MODEL_H_
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "content/public/common/media_stream_request.h"
+#include "ui/base/models/simple_menu_model.h"
+
+class MediaStreamInfoBarDelegate;
+
+// A menu model that builds the contents of the devices menu in the media stream
+// infobar. This menu has only one level (no submenus).
+class MediaStreamDevicesMenuModel : public ui::SimpleMenuModel,
+ public ui::SimpleMenuModel::Delegate {
+ public:
+ explicit MediaStreamDevicesMenuModel(
+ const MediaStreamInfoBarDelegate* delegate);
+ virtual ~MediaStreamDevicesMenuModel();
+
+ // Returns the |device_id| for the selected device of type |type|. Returns
+ // true if a selected device of the requested |type| was found, and false if
+ // none was found, in which case |device_id| remains untouched.
+ bool GetSelectedDeviceId(
+ content::MediaStreamDeviceType type,
+ std::string* device_id) const;
+
+ private:
+ typedef std::map<int, content::MediaStreamDevice> CommandMap;
+
+ // Internal method to add the |devices| to the current menu.
+ void AddDevices(const content::MediaStreamDevices& devices);
+
+ // ui::SimpleMenuModel::Delegate implementation:
+ virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
+ virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) OVERRIDE;
+ virtual void ExecuteCommand(int command_id) OVERRIDE;
+
+ // Map of command IDs to devices.
+ CommandMap commands_;
+
+ // These are the command IDs (key of above |commands_| map) of the selected
+ // devices entries in the menu, or -1 if there is no selected ID.
+ int selected_command_id_audio_;
+ int selected_command_id_video_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamDevicesMenuModel);
+};
+
+#endif // CHROME_BROWSER_MEDIA_MEDIA_STREAM_DEVICES_MENU_MODEL_H_
diff --git a/chrome/browser/ui/media_stream_infobar_delegate.cc b/chrome/browser/ui/media_stream_infobar_delegate.cc
new file mode 100644
index 0000000..ef7bab4
--- /dev/null
+++ b/chrome/browser/ui/media_stream_infobar_delegate.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <functional>
+
+#include "base/logging.h"
+#include "chrome/browser/ui/media_stream_infobar_delegate.h"
+#include "content/public/common/media_stream_request.h"
+#include "grit/theme_resources_standard.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+// A predicate that checks if a StreamDeviceInfo object has the same ID as the
+// device ID specified at construction.
+class DeviceIdEquals {
+ public:
+ explicit DeviceIdEquals(const std::string& device_id)
+ : device_id_(device_id) {
+ }
+
+ bool operator() (const content::MediaStreamDevice& device) {
+ return device.device_id == device_id_;
+ }
+
+ private:
+ std::string device_id_;
+};
+
+} // namespace
+
+MediaStreamInfoBarDelegate::MediaStreamInfoBarDelegate(
+ InfoBarTabHelper* tab_helper,
+ const content::MediaStreamRequest* request,
+ const content::MediaResponseCallback& callback)
+ : InfoBarDelegate(tab_helper),
+ request_(request),
+ callback_(callback) {
+ DCHECK(request_);
+ has_audio_ = request_->devices.count(
+ content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) != 0;
+ has_video_ = request_->devices.count(
+ content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) != 0;
+}
+
+MediaStreamInfoBarDelegate::~MediaStreamInfoBarDelegate() {
+}
+
+content::MediaStreamDevices
+ MediaStreamInfoBarDelegate::GetAudioDevices() const {
+ if (!has_audio_)
+ return content::MediaStreamDevices();
+ content::MediaStreamDeviceMap::const_iterator it =
+ request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
+ DCHECK(it != request_->devices.end());
+ return it->second;
+}
+
+content::MediaStreamDevices
+ MediaStreamInfoBarDelegate::GetVideoDevices() const {
+ if (!has_video_)
+ return content::MediaStreamDevices();
+ content::MediaStreamDeviceMap::const_iterator it =
+ request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
+ DCHECK(it != request_->devices.end());
+ return it->second;
+}
+
+const std::string& MediaStreamInfoBarDelegate::GetSecurityOrigin() const {
+ return request_->security_origin;
+}
+
+void MediaStreamInfoBarDelegate::Accept(const std::string& audio_id,
+ const std::string& video_id) {
+ content::MediaStreamDevices devices;
+
+ if (has_audio_) {
+ AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE,
+ audio_id, &devices);
+ }
+ if (has_video_) {
+ AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE,
+ video_id, &devices);
+ }
+
+ callback_.Run(devices);
+}
+
+void MediaStreamInfoBarDelegate::Deny() {
+ callback_.Run(content::MediaStreamDevices());
+}
+
+void MediaStreamInfoBarDelegate::AddDeviceWithId(
+ content::MediaStreamDeviceType type,
+ const std::string& id,
+ content::MediaStreamDevices* devices) {
+ DCHECK(devices);
+ content::MediaStreamDeviceMap::const_iterator device_it =
+ request_->devices.find(type);
+ if (device_it != request_->devices.end()) {
+ content::MediaStreamDevices::const_iterator it = std::find_if(
+ device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id));
+ if (it != device_it->second.end())
+ devices->push_back(*it);
+ }
+}
+
+// MediaStreamInfoBarDelegate::CreateInfoBar is implemented in platform-specific
+// files.
+
+#if !defined(TOOLKIT_VIEWS)
+// TODO(macourteau): This section is temporary, until the InfoBar is implemented
+// on other platforms, to make sure everything compiles and links.
+InfoBar* MediaStreamInfoBarDelegate::CreateInfoBar(InfoBarTabHelper* owner) {
+ DCHECK(owner);
+ return NULL;
+}
+#endif // !TOOLKIT_VIEWS
+
+void MediaStreamInfoBarDelegate::InfoBarDismissed() {
+ // Deny the request if the infobar was closed with the 'x' button, since
+ // we don't want WebRTC to be waiting for an answer that will never come.
+ Deny();
+}
+
+gfx::Image* MediaStreamInfoBarDelegate::GetIcon() const {
+ return &ResourceBundle::GetSharedInstance().GetNativeImageNamed(has_video_ ?
+ IDR_INFOBAR_MEDIA_STREAM_CAMERA : IDR_INFOBAR_MEDIA_STREAM_MIC);
+}
+
+InfoBarDelegate::Type MediaStreamInfoBarDelegate::GetInfoBarType() const {
+ return PAGE_ACTION_TYPE;
+}
+
+MediaStreamInfoBarDelegate*
+ MediaStreamInfoBarDelegate::AsMediaStreamInfobarDelegate() {
+ return this;
+}
diff --git a/chrome/browser/ui/media_stream_infobar_delegate.h b/chrome/browser/ui/media_stream_infobar_delegate.h
new file mode 100644
index 0000000..925e00d
--- /dev/null
+++ b/chrome/browser/ui/media_stream_infobar_delegate.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_MEDIA_STREAM_INFOBAR_DELEGATE_H_
+#define CHROME_BROWSER_UI_MEDIA_STREAM_INFOBAR_DELEGATE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/infobars/infobar_delegate.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/media_stream_request.h"
+
+class MessageLoop;
+class TabContents;
+class TabContentsWrapper;
+
+// This class configures an infobar shown when a page requests access to a
+// user's microphone and/or video camera. The user is shown a message asking
+// which audio and/or video devices he wishes to use with the current page, and
+// buttons to give access to the selected devices to the page, or to deny access
+// to them.
+class MediaStreamInfoBarDelegate : public InfoBarDelegate {
+ public:
+ MediaStreamInfoBarDelegate(
+ InfoBarTabHelper* tab_helper,
+ const content::MediaStreamRequest* request,
+ const content::MediaResponseCallback& callback);
+
+ virtual ~MediaStreamInfoBarDelegate();
+
+ // These tell whether the user has to select audio and/or video devices.
+ bool has_audio() const { return has_audio_; }
+ bool has_video() const { return has_video_; }
+
+ // Returns lists of audio and/or video devices from which the user will have
+ // to choose.
+ content::MediaStreamDevices GetAudioDevices() const;
+ content::MediaStreamDevices GetVideoDevices() const;
+
+ // Returns the security origin (e.g. "www.html5rocks.com") at the origin
+ // of this request.
+ const std::string& GetSecurityOrigin() const;
+
+ // Callbacks to handle accepting devices or denying the request. |audio_id|
+ // and |video_id| are the device IDs of the accepted audio and video devices.
+ // The |audio_id| or |video_id| values are ignored if the request did not ask
+ // for audio or video devices respectively.
+ void Accept(const std::string& audio_id, const std::string& video_id);
+ void Deny();
+
+ private:
+ // Finds a device in the current request with the specified |id| and |type|,
+ // and adds it to the |devices| array.
+ void AddDeviceWithId(content::MediaStreamDeviceType type,
+ const std::string& id,
+ content::MediaStreamDevices* devices);
+
+ // InfoBarDelegate:
+ virtual InfoBar* CreateInfoBar(InfoBarTabHelper* owner) OVERRIDE;
+ virtual void InfoBarDismissed() OVERRIDE;
+ virtual gfx::Image* GetIcon() const OVERRIDE;
+ virtual Type GetInfoBarType() const OVERRIDE;
+ virtual MediaStreamInfoBarDelegate* AsMediaStreamInfobarDelegate() OVERRIDE;
+
+ // The original request for access to devices.
+ const content::MediaStreamRequest* request_;
+
+ // The callback that needs to be Run to notify WebRTC of whether access to
+ // audio/video devices was granted or not.
+ content::MediaResponseCallback callback_;
+
+ // Whether the request is for audio and/or video devices.
+ bool has_audio_;
+ bool has_video_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamInfoBarDelegate);
+};
+
+#endif // CHROME_BROWSER_UI_MEDIA_STREAM_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/ui/views/infobars/media_stream_infobar.cc b/chrome/browser/ui/views/infobars/media_stream_infobar.cc
new file mode 100644
index 0000000..3bd6054
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/media_stream_infobar.cc
@@ -0,0 +1,129 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <string>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/infobars/infobar_tab_helper.h"
+#include "chrome/browser/ui/media_stream_infobar_delegate.h"
+#include "chrome/browser/ui/views/infobars/media_stream_infobar.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/views/controls/button/menu_button.h"
+#include "ui/views/controls/label.h"
+
+InfoBar* MediaStreamInfoBarDelegate::CreateInfoBar(InfoBarTabHelper* owner) {
+ DCHECK(owner);
+ return new MediaStreamInfoBar(owner, this);
+}
+
+MediaStreamInfoBar::MediaStreamInfoBar(
+ InfoBarTabHelper* owner,
+ MediaStreamInfoBarDelegate* delegate)
+ : InfoBarView(owner, delegate),
+ delegate_(delegate),
+ label_(NULL),
+ allow_button_(NULL),
+ deny_button_(NULL),
+ devices_menu_button_(NULL),
+ devices_menu_model_(delegate) {
+}
+
+MediaStreamInfoBar::~MediaStreamInfoBar() {
+}
+
+void MediaStreamInfoBar::Layout() {
+ InfoBarView::Layout();
+
+ int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth());
+ gfx::Size label_size = label_->GetPreferredSize();
+ label_->SetBounds(StartX(), OffsetY(label_size),
+ std::min(label_size.width(), available_width), label_size.height());
+ available_width = std::max(0, available_width - label_size.width());
+
+ gfx::Size allow_button_size = allow_button_->GetPreferredSize();
+ allow_button_->SetBounds(label_->bounds().right() + kEndOfLabelSpacing,
+ OffsetY(allow_button_size), allow_button_size.width(),
+ allow_button_size.height());
+
+ gfx::Size deny_button_size = deny_button_->GetPreferredSize();
+ deny_button_->SetBounds(
+ allow_button_->bounds().right() + kButtonButtonSpacing,
+ OffsetY(deny_button_size), deny_button_size.width(),
+ deny_button_size.height());
+
+ gfx::Size devices_size = devices_menu_button_->GetPreferredSize();
+ devices_menu_button_->SetBounds(EndX() - devices_size.width(),
+ OffsetY(devices_size), devices_size.width(), devices_size.height());
+}
+
+void MediaStreamInfoBar::ViewHierarchyChanged(bool is_add,
+ View* parent,
+ View* child) {
+ if (is_add && child == this && (label_ == NULL)) {
+ int message_id = IDS_MEDIA_CAPTURE_MIC_AND_VIDEO;
+ DCHECK(delegate_->has_audio() || delegate_->has_video());
+ if (!delegate_->has_audio())
+ message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY;
+ else if (!delegate_->has_video())
+ message_id = IDS_MEDIA_CAPTURE_MIC_ONLY;
+
+ label_ = CreateLabel(l10n_util::GetStringFUTF16(message_id,
+ UTF8ToUTF16(delegate_->GetSecurityOrigin())));
+ AddChildView(label_);
+
+ allow_button_ = CreateTextButton(this,
+ l10n_util::GetStringUTF16(IDS_MEDIA_CAPTURE_ALLOW), false);
+ AddChildView(allow_button_);
+
+ deny_button_ = CreateTextButton(this,
+ l10n_util::GetStringUTF16(IDS_MEDIA_CAPTURE_DENY), false);
+ AddChildView(deny_button_);
+
+ devices_menu_button_ = CreateMenuButton(
+ l10n_util::GetStringUTF16(IDS_MEDIA_CAPTURE_DEVICES_MENU_TITLE), this);
+ AddChildView(devices_menu_button_);
+ }
+
+ // This must happen after adding all other children so InfoBarView can ensure
+ // the close button is the last child.
+ InfoBarView::ViewHierarchyChanged(is_add, parent, child);
+}
+
+void MediaStreamInfoBar::ButtonPressed(views::Button* sender,
+ const views::Event& event) {
+ if (!owned())
+ return; // We're closing; don't call anything, it might access the owner.
+ if (sender == allow_button_) {
+ std::string audio_id, video_id;
+ devices_menu_model_.GetSelectedDeviceId(
+ content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, &audio_id);
+ devices_menu_model_.GetSelectedDeviceId(
+ content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, &video_id);
+ delegate_->Accept(audio_id, video_id);
+ RemoveSelf();
+ } else if (sender == deny_button_) {
+ delegate_->Deny();
+ RemoveSelf();
+ } else {
+ InfoBarView::ButtonPressed(sender, event);
+ }
+}
+
+int MediaStreamInfoBar::ContentMinimumWidth() const {
+ return
+ kEndOfLabelSpacing +
+ (allow_button_->GetPreferredSize().width() + kButtonButtonSpacing +
+ deny_button_->GetPreferredSize().width()) +
+ (kButtonButtonSpacing + devices_menu_button_->GetPreferredSize().width());
+}
+
+void MediaStreamInfoBar::RunMenu(View* source, const gfx::Point& pt) {
+ if (!owned())
+ return; // We're closing; don't call anything, it might access the owner.
+ DCHECK_EQ(devices_menu_button_, source);
+ RunMenuAt(&devices_menu_model_, devices_menu_button_,
+ views::MenuItemView::TOPRIGHT);
+}
diff --git a/chrome/browser/ui/views/infobars/media_stream_infobar.h b/chrome/browser/ui/views/infobars/media_stream_infobar.h
new file mode 100644
index 0000000..a5a913e
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/media_stream_infobar.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_INFOBARS_MEDIA_STREAM_INFOBAR_H_
+#define CHROME_BROWSER_UI_VIEWS_INFOBARS_MEDIA_STREAM_INFOBAR_H_
+#pragma once
+
+#include "chrome/browser/infobars/infobar_delegate.h"
+#include "chrome/browser/media/media_stream_devices_menu_model.h"
+#include "chrome/browser/ui/views/infobars/infobar_background.h"
+#include "chrome/browser/ui/views/infobars/infobar_view.h"
+#include "ui/views/controls/menu/view_menu_delegate.h"
+
+class MediaStreamInfoBarDelegate;
+
+namespace views {
+class MenuButton;
+}
+
+// Views implementation of the Media Stream InfoBar, which asks the user whether
+// he wants to grant access to his camera/microphone to the current webpage. It
+// also provides a way for the user to select which device(s) will be used by
+// the page.
+class MediaStreamInfoBar : public InfoBarView, public views::ViewMenuDelegate {
+ public:
+ MediaStreamInfoBar(InfoBarTabHelper* contents,
+ MediaStreamInfoBarDelegate* delegate);
+
+ private:
+ virtual ~MediaStreamInfoBar();
+
+ // InfoBarView:
+ virtual void Layout() OVERRIDE;
+ virtual void ViewHierarchyChanged(bool is_add,
+ View* parent,
+ View* child) OVERRIDE;
+ virtual void ButtonPressed(views::Button* sender,
+ const views::Event& event) OVERRIDE;
+ virtual int ContentMinimumWidth() const OVERRIDE;
+
+ // views::ViewMenuDelegate:
+ virtual void RunMenu(View* source, const gfx::Point& pt) OVERRIDE;
+
+ MediaStreamInfoBarDelegate* delegate_;
+
+ views::Label* label_;
+ views::TextButton* allow_button_;
+ views::TextButton* deny_button_;
+ views::MenuButton* devices_menu_button_;
+
+ MediaStreamDevicesMenuModel devices_menu_model_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamInfoBar);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_INFOBARS_MEDIA_STREAM_INFOBAR_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index a446acd..1b29ea5 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1688,6 +1688,8 @@
'browser/mac/scoped_launch_data.h',
'browser/media/media_internals.cc',
'browser/media/media_internals.h',
+ 'browser/media/media_stream_devices_menu_model.cc',
+ 'browser/media/media_stream_devices_menu_model.h',
'browser/memory_details.cc',
'browser/memory_details.h',
'browser/memory_details_android.cc',
@@ -3375,6 +3377,8 @@
'browser/ui/login/login_prompt_mac.mm',
'browser/ui/login/login_prompt_ui.cc',
'browser/ui/login/login_prompt_win.cc',
+ 'browser/ui/media_stream_infobar_delegate.cc',
+ 'browser/ui/media_stream_infobar_delegate.cc',
'browser/ui/omnibox/location_bar.h',
'browser/ui/omnibox/location_bar_util.cc',
'browser/ui/omnibox/location_bar_util.h',
@@ -3726,6 +3730,8 @@
'browser/ui/views/infobars/infobar_view.h',
'browser/ui/views/infobars/link_infobar.cc',
'browser/ui/views/infobars/link_infobar.h',
+ 'browser/ui/views/infobars/media_stream_infobar.cc',
+ 'browser/ui/views/infobars/media_stream_infobar.h',
'browser/ui/views/infobars/translate_infobar_base.cc',
'browser/ui/views/infobars/translate_infobar_base.h',
'browser/ui/views/infobars/translate_message_infobar.cc',
diff --git a/content/browser/renderer_host/media/media_stream_device_settings.cc b/content/browser/renderer_host/media/media_stream_device_settings.cc
index 3347480..0f473bd 100644
--- a/content/browser/renderer_host/media/media_stream_device_settings.cc
+++ b/content/browser/renderer_host/media/media_stream_device_settings.cc
@@ -39,7 +39,7 @@ class ResponseCallbackHelper
}
void PostResponse(const std::string& label,
- const content::MediaStreamDeviceArray& devices) {
+ const content::MediaStreamDevices& devices) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -214,7 +214,7 @@ void MediaStreamDeviceSettings::AvailableDevices(
void MediaStreamDeviceSettings::PostResponse(
const std::string& label,
- const content::MediaStreamDeviceArray& devices) {
+ const content::MediaStreamDevices& devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
SettingsRequests::iterator req = requests_.find(label);
@@ -224,7 +224,7 @@ void MediaStreamDeviceSettings::PostResponse(
if (devices.size() > 0) {
// Build a list of "full" device objects for the accepted devices.
StreamDeviceInfoArray deviceList;
- for (content::MediaStreamDeviceArray::const_iterator dev = devices.begin();
+ for (content::MediaStreamDevices::const_iterator dev = devices.begin();
dev != devices.end(); ++dev) {
DeviceMap::iterator subList = req->second->devices_full.find(dev->type);
DCHECK(subList != req->second->devices_full.end());
diff --git a/content/browser/renderer_host/media/media_stream_device_settings.h b/content/browser/renderer_host/media/media_stream_device_settings.h
index 55b6d44..0a83cda 100644
--- a/content/browser/renderer_host/media/media_stream_device_settings.h
+++ b/content/browser/renderer_host/media/media_stream_device_settings.h
@@ -64,7 +64,7 @@ class CONTENT_EXPORT MediaStreamDeviceSettings
// the requester. An empty list of devices means that access has been denied.
// This method must be called on the IO thread.
void PostResponse(const std::string& label,
- const content::MediaStreamDeviceArray& devices);
+ const content::MediaStreamDevices& devices);
// Used for testing only. This function is called to use faked UI, which is
// needed for server based tests. The first non-opened device(s) will be
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index a6adede..d848406 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -66,7 +66,7 @@ class BrowserContext;
class ResourceContext;
class WebUIControllerFactory;
-typedef base::Callback< void(const content::MediaStreamDeviceArray&) >
+typedef base::Callback< void(const content::MediaStreamDevices&) >
MediaResponseCallback;
// Embedder API (or SPI) for participating in browser logic, to be implemented
diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h
index 7a5eceb..df9ce4e 100644
--- a/content/public/common/media_stream_request.h
+++ b/content/public/common/media_stream_request.h
@@ -39,9 +39,9 @@ struct CONTENT_EXPORT MediaStreamDevice {
std::string name;
};
-typedef std::vector<MediaStreamDevice> MediaStreamDeviceArray;
+typedef std::vector<MediaStreamDevice> MediaStreamDevices;
-typedef std::map<MediaStreamDeviceType, MediaStreamDeviceArray>
+typedef std::map<MediaStreamDeviceType, MediaStreamDevices>
MediaStreamDeviceMap;
// Represents a request for media streams (audio/video).