// 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_controller.h"

#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/values.h"
#include "chrome/browser/content_settings/content_settings_provider.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/media_stream_capture_indicator.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/content_settings_pattern.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/media_stream_request.h"
#include "extensions/common/constants.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/user_manager.h"
#endif

using content::BrowserThread;

namespace {

bool HasAnyAvailableDevice() {
  const content::MediaStreamDevices& audio_devices =
      MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices();
  const content::MediaStreamDevices& video_devices =
      MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();

  return !audio_devices.empty() || !video_devices.empty();
}

bool IsInKioskMode() {
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
    return true;

#if defined(OS_CHROMEOS)
  const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
  return user_manager && user_manager->IsLoggedInAsKioskApp();
#else
  return false;
#endif
}

}  // namespace

MediaStreamDevicesController::MediaStreamTypeSettings::MediaStreamTypeSettings(
    Permission permission, const std::string& requested_device_id):
    permission(permission), requested_device_id(requested_device_id) {}

MediaStreamDevicesController::MediaStreamTypeSettings::
    MediaStreamTypeSettings(): permission(MEDIA_NONE) {}

MediaStreamDevicesController::MediaStreamTypeSettings::
    ~MediaStreamTypeSettings() {}

MediaStreamDevicesController::MediaStreamDevicesController(
    content::WebContents* web_contents,
    const content::MediaStreamRequest& request,
    const content::MediaResponseCallback& callback)
    : web_contents_(web_contents),
      request_(request),
      callback_(callback) {
  profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
  content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);

  // For MEDIA_OPEN_DEVICE requests (Pepper) we always request both webcam
  // and microphone to avoid popping two infobars.
  // We start with setting the requested media type to allowed or blocked
  // depending on the policy. If not blocked by policy it may be blocked later
  // in the two remaining filtering steps (by user setting or by user when
  // clicking the infobar).
  // TODO(grunell): It's not the nicest solution to let the MEDIA_OPEN_DEVICE
  // case take a ride on the MEDIA_DEVICE_*_CAPTURE permission. Should be fixed.
  if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
      request.request_type == content::MEDIA_OPEN_DEVICE) {
    if (GetDevicePolicy(prefs::kAudioCaptureAllowed,
                        prefs::kAudioCaptureAllowedUrls) == ALWAYS_DENY) {
      request_permissions_.insert(std::make_pair(
          content::MEDIA_DEVICE_AUDIO_CAPTURE,
          MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
                                  request.requested_audio_device_id)));
    } else {
      request_permissions_.insert(std::make_pair(
          content::MEDIA_DEVICE_AUDIO_CAPTURE,
          MediaStreamTypeSettings(MEDIA_ALLOWED,
                                  request.requested_audio_device_id)));
    }
  }
  if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ||
      request.request_type == content::MEDIA_OPEN_DEVICE) {
    if (GetDevicePolicy(prefs::kVideoCaptureAllowed,
                        prefs::kVideoCaptureAllowedUrls) == ALWAYS_DENY) {
      request_permissions_.insert(std::make_pair(
          content::MEDIA_DEVICE_VIDEO_CAPTURE,
          MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
                                  request.requested_video_device_id)));
    } else {
      request_permissions_.insert(std::make_pair(
          content::MEDIA_DEVICE_VIDEO_CAPTURE,
          MediaStreamTypeSettings(MEDIA_ALLOWED,
                                  request.requested_video_device_id)));
    }
  }
}

MediaStreamDevicesController::~MediaStreamDevicesController() {
  if (!callback_.is_null()) {
    callback_.Run(content::MediaStreamDevices(),
                  scoped_ptr<content::MediaStreamUI>());
  }
}

// static
void MediaStreamDevicesController::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* prefs) {
  prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed,
                             true,
                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed,
                             true,
                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls,
                          user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls,
                          user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}


bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
  // Tab capture is allowed for extensions only and infobar is not shown for
  // extensions.
  if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE ||
      request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
    Deny(false);
    return true;
  }

  // Deny the request if the security origin is empty, this happens with
  // file access without |--allow-file-access-from-files| flag.
  if (request_.security_origin.is_empty()) {
    Deny(false);
    return true;
  }

  // Deny the request if there is no device attached to the OS.
  if (!HasAnyAvailableDevice()) {
    Deny(false);
    return true;
  }

  // Check if any allow exception has been made for this request.
  if (IsRequestAllowedByDefault()) {
    Accept(false);
    return true;
  }

  // Filter any parts of the request that have been blocked by default and deny
  // it if nothing is left to accept.
  if (FilterBlockedByDefaultDevices() == 0) {
    Deny(false);
    return true;
  }

  // Check if the media default setting is set to block.
  if (IsDefaultMediaAccessBlocked()) {
    Deny(false);
    return true;
  }

  if (request_.request_type == content::MEDIA_OPEN_DEVICE) {
    bool no_matched_audio_device =
        (request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE &&
         !request_.requested_audio_device_id.empty() &&
         MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedAudioDevice(
             request_.requested_audio_device_id) == NULL);
    bool no_matched_video_device =
        (request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE &&
         !request_.requested_video_device_id.empty() &&
         MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedVideoDevice(
             request_.requested_video_device_id) == NULL);
    if (no_matched_audio_device || no_matched_video_device) {
      Deny(false);
      return true;
    }
  }

  // Show the infobar.
  return false;
}

bool MediaStreamDevicesController::HasAudio() const {
  return IsDeviceAudioCaptureRequestedAndAllowed();
}

bool MediaStreamDevicesController::HasVideo() const {
  return IsDeviceVideoCaptureRequestedAndAllowed();
}

const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
  return request_.security_origin.spec();
}

void MediaStreamDevicesController::Accept(bool update_content_setting) {
  NotifyUIRequestAccepted();

  // Get the default devices for the request.
  content::MediaStreamDevices devices;
  bool audio_allowed = IsDeviceAudioCaptureRequestedAndAllowed();
  bool video_allowed = IsDeviceVideoCaptureRequestedAndAllowed();
  if (audio_allowed || video_allowed) {
    switch (request_.request_type) {
      case content::MEDIA_OPEN_DEVICE: {
        const content::MediaStreamDevice* device = NULL;
        // For open device request, when requested device_id is empty, pick
        // the first available of the given type. If requested device_id is
        // not empty, return the desired device if it's available. Otherwise,
        // return no device.
        if (audio_allowed &&
            request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
          if (!request_.requested_audio_device_id.empty()) {
            device = MediaCaptureDevicesDispatcher::GetInstance()->
                GetRequestedAudioDevice(request_.requested_audio_device_id);
          } else {
            device = MediaCaptureDevicesDispatcher::GetInstance()->
                GetFirstAvailableAudioDevice();
          }
        } else if (video_allowed &&
            request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
          // Pepper API opens only one device at a time.
          if (!request_.requested_video_device_id.empty()) {
            device = MediaCaptureDevicesDispatcher::GetInstance()->
                GetRequestedVideoDevice(request_.requested_video_device_id);
          } else {
            device = MediaCaptureDevicesDispatcher::GetInstance()->
                GetFirstAvailableVideoDevice();
          }
        }
        if (device)
          devices.push_back(*device);
        break;
      }
      case content::MEDIA_GENERATE_STREAM: {
        bool get_default_audio_device = audio_allowed;
        bool get_default_video_device = video_allowed;

        // Get the exact audio or video device if an id is specified.
        if (audio_allowed && !request_.requested_audio_device_id.empty()) {
          const content::MediaStreamDevice* audio_device =
              MediaCaptureDevicesDispatcher::GetInstance()->
                  GetRequestedAudioDevice(request_.requested_audio_device_id);
          if (audio_device) {
            devices.push_back(*audio_device);
            get_default_audio_device = false;
          }
        }
        if (video_allowed && !request_.requested_video_device_id.empty()) {
          const content::MediaStreamDevice* video_device =
              MediaCaptureDevicesDispatcher::GetInstance()->
                  GetRequestedVideoDevice(request_.requested_video_device_id);
          if (video_device) {
            devices.push_back(*video_device);
            get_default_video_device = false;
          }
        }

        // If either or both audio and video devices were requested but not
        // specified by id, get the default devices.
        if (get_default_audio_device || get_default_video_device) {
          MediaCaptureDevicesDispatcher::GetInstance()->
              GetDefaultDevicesForProfile(profile_,
                                          get_default_audio_device,
                                          get_default_video_device,
                                          &devices);
        }
        break;
      }
      case content::MEDIA_DEVICE_ACCESS: {
        // Get the default devices for the request.
        MediaCaptureDevicesDispatcher::GetInstance()->
            GetDefaultDevicesForProfile(profile_,
                                        audio_allowed,
                                        video_allowed,
                                        &devices);
        break;
      }
      case content::MEDIA_ENUMERATE_DEVICES: {
        // Do nothing.
        NOTREACHED();
        break;
      }
    }  // switch

    // TODO(raymes): We currently set the content permission for non-https
    // websites for Pepper requests as well. This is temporary and should be
    // removed.
    if (update_content_setting) {
      if ((IsSchemeSecure() && !devices.empty()) ||
          request_.request_type == content::MEDIA_OPEN_DEVICE) {
        SetPermission(true);
      }
    }
  }

  scoped_ptr<content::MediaStreamUI> ui;
  if (!devices.empty()) {
    ui = MediaCaptureDevicesDispatcher::GetInstance()->
        GetMediaStreamCaptureIndicator()->RegisterMediaStream(
            web_contents_, devices);
  }
  content::MediaResponseCallback cb = callback_;
  callback_.Reset();
  cb.Run(devices, ui.Pass());
}

void MediaStreamDevicesController::Deny(bool update_content_setting) {
  NotifyUIRequestDenied();

  if (update_content_setting)
    SetPermission(false);

  content::MediaResponseCallback cb = callback_;
  callback_.Reset();
  cb.Run(content::MediaStreamDevices(), scoped_ptr<content::MediaStreamUI>());
}

MediaStreamDevicesController::DevicePolicy
MediaStreamDevicesController::GetDevicePolicy(
    const char* policy_name,
    const char* whitelist_policy_name) const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // If the security origin policy matches a value in the whitelist, allow it.
  // Otherwise, check the |policy_name| master switch for the default behavior.

  PrefService* prefs = profile_->GetPrefs();

  // TODO(tommi): Remove the kiosk mode check when the whitelist below
  // is visible in the media exceptions UI.
  // See discussion here: https://codereview.chromium.org/15738004/
  if (IsInKioskMode()) {
    const base::ListValue* list = prefs->GetList(whitelist_policy_name);
    std::string value;
    for (size_t i = 0; i < list->GetSize(); ++i) {
      if (list->GetString(i, &value)) {
        ContentSettingsPattern pattern =
            ContentSettingsPattern::FromString(value);
        if (pattern == ContentSettingsPattern::Wildcard()) {
          DLOG(WARNING) << "Ignoring wildcard URL pattern: " << value;
          continue;
        }
        DLOG_IF(ERROR, !pattern.IsValid()) << "Invalid URL pattern: " << value;
        if (pattern.IsValid() && pattern.Matches(request_.security_origin))
          return ALWAYS_ALLOW;
      }
    }
  }

  // If a match was not found, check if audio capture is otherwise disallowed
  // or if the user should be prompted.  Setting the policy value to "true"
  // is equal to not setting it at all, so from hereon out, we will return
  // either POLICY_NOT_SET (prompt) or ALWAYS_DENY (no prompt, no access).
  if (!prefs->GetBoolean(policy_name))
    return ALWAYS_DENY;

  return POLICY_NOT_SET;
}

bool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
  // The request from internal objects like chrome://URLs is always allowed.
  if (ShouldAlwaysAllowOrigin())
    return true;

  struct {
    bool has_capability;
    const char* policy_name;
    const char* list_policy_name;
    ContentSettingsType settings_type;
  } device_checks[] = {
    { IsDeviceAudioCaptureRequestedAndAllowed(), prefs::kAudioCaptureAllowed,
      prefs::kAudioCaptureAllowedUrls, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC },
    { IsDeviceVideoCaptureRequestedAndAllowed(), prefs::kVideoCaptureAllowed,
      prefs::kVideoCaptureAllowedUrls,
      CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA },
  };

  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(device_checks); ++i) {
    if (!device_checks[i].has_capability)
      continue;

    DevicePolicy policy = GetDevicePolicy(device_checks[i].policy_name,
                                          device_checks[i].list_policy_name);

    if (policy == ALWAYS_DENY)
      return false;

    if (policy == POLICY_NOT_SET) {
      // Only load content settings from secure origins unless it is a
      // content::MEDIA_OPEN_DEVICE (Pepper) request.
      if (!IsSchemeSecure() &&
          request_.request_type != content::MEDIA_OPEN_DEVICE) {
        return false;
      }
      if (profile_->GetHostContentSettingsMap()->GetContentSetting(
              request_.security_origin, request_.security_origin,
              device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) !=
              CONTENT_SETTING_ALLOW) {
        return false;
      }
    }
    // If we get here, then either policy is set to ALWAYS_ALLOW or the content
    // settings allow the request by default.
  }

  return true;
}

int MediaStreamDevicesController::FilterBlockedByDefaultDevices() {
  int requested_devices = 0;

  if (IsDeviceAudioCaptureRequestedAndAllowed()) {
    if (profile_->GetHostContentSettingsMap()->GetContentSetting(
        request_.security_origin,
        request_.security_origin,
        CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
        NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
      request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
          MEDIA_BLOCKED_BY_USER_SETTING;
    } else {
      ++requested_devices;
    }
  }

  if (IsDeviceVideoCaptureRequestedAndAllowed()) {
    if (profile_->GetHostContentSettingsMap()->GetContentSetting(
        request_.security_origin,
        request_.security_origin,
        CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
        NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
      request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
          MEDIA_BLOCKED_BY_USER_SETTING;
    } else {
      ++requested_devices;
    }
  }

  return requested_devices;
}

bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
  // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
  // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
  ContentSetting current_setting =
      profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
          CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
  return (current_setting == CONTENT_SETTING_BLOCK);
}

bool MediaStreamDevicesController::IsSchemeSecure() const {
  return request_.security_origin.SchemeIsSecure() ||
      request_.security_origin.SchemeIs(extensions::kExtensionScheme) ||
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableUserMediaSecurity);
}

bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() const {
  // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
  // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
  // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
  return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
      request_.security_origin, request_.security_origin,
      CONTENT_SETTINGS_TYPE_MEDIASTREAM);
}

void MediaStreamDevicesController::SetPermission(bool allowed) const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  ContentSettingsPattern primary_pattern =
      ContentSettingsPattern::FromURLNoWildcard(request_.security_origin);
  // Check the pattern is valid or not. When the request is from a file access,
  // no exception will be made.
  if (!primary_pattern.IsValid())
    return;

  ContentSetting content_setting = allowed ?
      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
  if (request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE) !=
      request_permissions_.end()) {
      profile_->GetHostContentSettingsMap()->SetContentSetting(
        primary_pattern,
        ContentSettingsPattern::Wildcard(),
        CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
        std::string(),
        content_setting);
  }
  if (request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE) !=
      request_permissions_.end()) {
    profile_->GetHostContentSettingsMap()->SetContentSetting(
        primary_pattern,
        ContentSettingsPattern::Wildcard(),
        CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
        std::string(),
        content_setting);
  }
}

void MediaStreamDevicesController::NotifyUIRequestAccepted() const {
  if (!content_settings_)
    return;

  content_settings_->OnMediaStreamPermissionSet(request_.security_origin,
                                                request_permissions_);
}

void MediaStreamDevicesController::NotifyUIRequestDenied() {
  if (!content_settings_)
    return;

  if (IsDeviceAudioCaptureRequestedAndAllowed()) {
    request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
        MEDIA_BLOCKED_BY_USER;
  }
  if (IsDeviceVideoCaptureRequestedAndAllowed()) {
    request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
        MEDIA_BLOCKED_BY_USER;
  }

  content_settings_->OnMediaStreamPermissionSet(request_.security_origin,
                                                request_permissions_);
}

bool MediaStreamDevicesController::IsDeviceAudioCaptureRequestedAndAllowed()
    const {
  MediaStreamTypeSettingsMap::const_iterator it =
      request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE);
  return (it != request_permissions_.end() &&
          it->second.permission == MEDIA_ALLOWED);
}

bool MediaStreamDevicesController::IsDeviceVideoCaptureRequestedAndAllowed()
    const {
  MediaStreamTypeSettingsMap::const_iterator it =
      request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE);
  return (it != request_permissions_.end() &&
          it->second.permission == MEDIA_ALLOWED);
}
