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_infobar_delegate.h"
6
7#include "base/logging.h"
8#include "base/metrics/histogram.h"
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/browser/infobars/infobar_service.h"
11#include "chrome/common/url_constants.h"
12#include "chrome/grit/generated_resources.h"
13#include "components/google/core/browser/google_util.h"
14#include "components/infobars/core/infobar.h"
15#include "content/public/browser/web_contents.h"
16#include "grit/components_strings.h"
17#include "grit/theme_resources.h"
18#include "ui/base/l10n/l10n_util.h"
19#include "url/gurl.h"
20
21namespace {
22
23enum DevicePermissionActions {
24  kAllowHttps = 0,
25  kAllowHttp,
26  kDeny,
27  kCancel,
28  kPermissionActionsMax  // Must always be last!
29};
30
31}  // namespace
32
33MediaStreamInfoBarDelegate::~MediaStreamInfoBarDelegate() {
34}
35
36// static
37bool MediaStreamInfoBarDelegate::Create(
38    content::WebContents* web_contents,
39    const content::MediaStreamRequest& request,
40    const content::MediaResponseCallback& callback) {
41  scoped_ptr<MediaStreamDevicesController> controller(
42      new MediaStreamDevicesController(web_contents, request, callback));
43  if (controller->DismissInfoBarAndTakeActionOnSettings())
44    return false;
45
46  InfoBarService* infobar_service =
47      InfoBarService::FromWebContents(web_contents);
48  if (!infobar_service) {
49    // Deny the request if there is no place to show the infobar, e.g. when
50    // the request comes from a background extension page.
51    controller->Deny(false, content::MEDIA_DEVICE_INVALID_STATE);
52    return false;
53  }
54
55  scoped_ptr<infobars::InfoBar> infobar(
56      ConfirmInfoBarDelegate::CreateInfoBar(scoped_ptr<ConfirmInfoBarDelegate>(
57          new MediaStreamInfoBarDelegate(controller.Pass()))));
58  for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
59    infobars::InfoBar* old_infobar = infobar_service->infobar_at(i);
60    if (old_infobar->delegate()->AsMediaStreamInfoBarDelegate()) {
61      infobar_service->ReplaceInfoBar(old_infobar, infobar.Pass());
62      return true;
63    }
64  }
65  infobar_service->AddInfoBar(infobar.Pass());
66  return true;
67}
68
69MediaStreamInfoBarDelegate::MediaStreamInfoBarDelegate(
70    scoped_ptr<MediaStreamDevicesController> controller)
71    : ConfirmInfoBarDelegate(),
72      controller_(controller.Pass()) {
73  DCHECK(controller_.get());
74  DCHECK(controller_->HasAudio() || controller_->HasVideo());
75}
76
77void MediaStreamInfoBarDelegate::InfoBarDismissed() {
78  // Deny the request if the infobar was closed with the 'x' button, since
79  // we don't want WebRTC to be waiting for an answer that will never come.
80  UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
81                            kCancel, kPermissionActionsMax);
82  controller_->Deny(false, content::MEDIA_DEVICE_PERMISSION_DISMISSED);
83}
84
85int MediaStreamInfoBarDelegate::GetIconID() const {
86  return controller_->HasVideo() ?
87      IDR_INFOBAR_MEDIA_STREAM_CAMERA : IDR_INFOBAR_MEDIA_STREAM_MIC;
88}
89
90infobars::InfoBarDelegate::Type MediaStreamInfoBarDelegate::GetInfoBarType()
91    const {
92  return PAGE_ACTION_TYPE;
93}
94
95MediaStreamInfoBarDelegate*
96    MediaStreamInfoBarDelegate::AsMediaStreamInfoBarDelegate() {
97  return this;
98}
99
100base::string16 MediaStreamInfoBarDelegate::GetMessageText() const {
101  int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO;
102  if (!controller_->HasAudio())
103    message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY;
104  else if (!controller_->HasVideo())
105    message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY;
106  return l10n_util::GetStringFUTF16(
107      message_id, base::UTF8ToUTF16(controller_->GetSecurityOriginSpec()));
108}
109
110base::string16 MediaStreamInfoBarDelegate::GetButtonLabel(
111    InfoBarButton button) const {
112  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
113      IDS_MEDIA_CAPTURE_ALLOW : IDS_MEDIA_CAPTURE_DENY);
114}
115
116bool MediaStreamInfoBarDelegate::Accept() {
117  GURL origin(controller_->GetSecurityOriginSpec());
118  if (origin.SchemeIsSecure()) {
119    UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
120                              kAllowHttps, kPermissionActionsMax);
121  } else {
122    UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
123                              kAllowHttp, kPermissionActionsMax);
124  }
125  controller_->Accept(true);
126  return true;
127}
128
129bool MediaStreamInfoBarDelegate::Cancel() {
130  UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
131                            kDeny, kPermissionActionsMax);
132  controller_->Deny(true, content::MEDIA_DEVICE_PERMISSION_DENIED);
133  return true;
134}
135
136base::string16 MediaStreamInfoBarDelegate::GetLinkText() const {
137  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
138}
139
140bool MediaStreamInfoBarDelegate::LinkClicked(
141    WindowOpenDisposition disposition) {
142  InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
143      content::OpenURLParams(
144          GURL(chrome::kMediaAccessLearnMoreUrl),
145          content::Referrer(),
146          (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
147          ui::PAGE_TRANSITION_LINK, false));
148
149  return false;  // Do not dismiss the info bar.
150}
151