blob: 2835818bc44e0c884fbc9186e61e287cc2f4ff38 [file] [log] [blame]
// Copyright 2016 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 "content/public/browser/web_contents_media_capture_id.h"
#include <tuple>
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
namespace {
constexpr char kWebContentsCaptureScheme[] = "web-contents-media-stream://";
constexpr char kEnableThrottlingFlag[] = "throttling=auto";
constexpr char kDisableLocalEchoFlag[] = "local_echo=false";
constexpr char kOptionStart = '?';
constexpr char kOptionSeparator = '&';
bool ExtractTabCaptureTarget(const std::string& device_id_param,
int* render_process_id,
int* main_render_frame_id) {
const std::string device_scheme = kWebContentsCaptureScheme;
if (!base::StartsWith(device_id_param, device_scheme,
base::CompareCase::SENSITIVE))
return false;
const std::string device_id = device_id_param.substr(device_scheme.size());
const size_t sep_pos = device_id.find(':');
if (sep_pos == std::string::npos)
return false;
const base::StringPiece component1(device_id.data(), sep_pos);
size_t end_pos = device_id.find('?');
if (end_pos == std::string::npos)
end_pos = device_id.length();
const base::StringPiece component2(device_id.data() + sep_pos + 1,
end_pos - sep_pos - 1);
return (base::StringToInt(component1, render_process_id) &&
base::StringToInt(component2, main_render_frame_id));
}
bool ExtractOptions(const std::string& device_id,
bool* auto_throttling,
bool* disable_local_echo) {
DCHECK(auto_throttling);
DCHECK(disable_local_echo);
*auto_throttling = false;
*disable_local_echo = false;
// Find the option part of the string and just do a naive string compare since
// there are no other options in the |device_id| to account for (at the time
// of this writing).
size_t option_pos = device_id.find(kOptionStart);
if (option_pos == std::string::npos)
return true;
size_t option_pos_end;
while (option_pos < device_id.length()) {
option_pos_end = device_id.find(kOptionSeparator, option_pos + 1);
if (option_pos_end == std::string::npos)
option_pos_end = device_id.length();
const base::StringPiece component(device_id.data() + option_pos + 1,
option_pos_end - option_pos - 1);
if (component.compare(kEnableThrottlingFlag) == 0)
*auto_throttling = true;
else if (component.compare(kDisableLocalEchoFlag) == 0)
*disable_local_echo = true;
else // Some unknown parameter is specified, and thus this ID is invalid.
return false;
option_pos = option_pos_end;
}
return true;
}
} // namespace
namespace content {
bool WebContentsMediaCaptureId::operator<(
const WebContentsMediaCaptureId& other) const {
return std::tie(render_process_id, main_render_frame_id,
enable_auto_throttling, disable_local_echo) <
std::tie(other.render_process_id, other.main_render_frame_id,
other.enable_auto_throttling, other.disable_local_echo);
}
bool WebContentsMediaCaptureId::operator==(
const WebContentsMediaCaptureId& other) const {
return std::tie(render_process_id, main_render_frame_id,
enable_auto_throttling, disable_local_echo) ==
std::tie(other.render_process_id, other.main_render_frame_id,
other.enable_auto_throttling, other.disable_local_echo);
}
bool WebContentsMediaCaptureId::is_null() const {
return (render_process_id < 0) || (main_render_frame_id < 0);
}
std::string WebContentsMediaCaptureId::ToString() const {
std::string s = kWebContentsCaptureScheme;
s.append(base::Int64ToString(render_process_id));
s.append(":");
s.append(base::Int64ToString(main_render_frame_id));
char connector = kOptionStart;
if (enable_auto_throttling) {
s += connector;
s.append(kEnableThrottlingFlag);
connector = kOptionSeparator;
}
if (disable_local_echo) {
s += connector;
s.append(kDisableLocalEchoFlag);
connector = kOptionSeparator;
}
return s;
}
// static
bool WebContentsMediaCaptureId::Parse(const std::string& str,
WebContentsMediaCaptureId* output_id) {
int render_process_id;
int main_render_frame_id;
if (!ExtractTabCaptureTarget(str, &render_process_id, &main_render_frame_id))
return false;
bool auto_throttling, disable_local_echo;
if (!ExtractOptions(str, &auto_throttling, &disable_local_echo))
return false;
if (output_id) {
output_id->render_process_id = render_process_id;
output_id->main_render_frame_id = main_render_frame_id;
output_id->enable_auto_throttling = auto_throttling;
output_id->disable_local_echo = disable_local_echo;
}
return true;
}
} // namespace content