blob: 3c939662cb2b10c53a31cf267f8523dbe5ba1413 [file] [log] [blame]
// Copyright 2013 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/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h"
#include "base/command_line.h"
#include "base/hash.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/supports_user_data.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/error_utils.h"
namespace extensions {
using api::webrtc_logging_private::MetaDataEntry;
using api::webrtc_logging_private::RequestInfo;
using content::BrowserThread;
namespace Discard = api::webrtc_logging_private::Discard;
namespace SetMetaData = api::webrtc_logging_private::SetMetaData;
namespace SetUploadOnRenderClose =
api::webrtc_logging_private::SetUploadOnRenderClose;
namespace Start = api::webrtc_logging_private::Start;
namespace StartRtpDump = api::webrtc_logging_private::StartRtpDump;
namespace Stop = api::webrtc_logging_private::Stop;
namespace StopRtpDump = api::webrtc_logging_private::StopRtpDump;
namespace Store = api::webrtc_logging_private::Store;
namespace Upload = api::webrtc_logging_private::Upload;
namespace UploadStored = api::webrtc_logging_private::UploadStored;
namespace StartAudioDebugRecordings =
api::webrtc_logging_private::StartAudioDebugRecordings;
namespace StopAudioDebugRecordings =
api::webrtc_logging_private::StopAudioDebugRecordings;
namespace StartWebRtcEventLogging =
api::webrtc_logging_private::StartWebRtcEventLogging;
namespace StopWebRtcEventLogging =
api::webrtc_logging_private::StopWebRtcEventLogging;
namespace {
std::string HashIdWithOrigin(const std::string& security_origin,
const std::string& log_id) {
return base::UintToString(base::Hash(security_origin + log_id));
}
} // namespace
content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest(
const RequestInfo& request, const std::string& security_origin) {
// If |guest_process_id| is defined, directly use this id to find the
// corresponding RenderProcessHost.
if (request.guest_process_id.get())
return content::RenderProcessHost::FromID(*request.guest_process_id.get());
// Otherwise, use the |tab_id|. If there's no |tab_id| and no
// |guest_process_id|, we can't look up the RenderProcessHost.
if (!request.tab_id.get())
return NULL;
int tab_id = *request.tab_id.get();
content::WebContents* contents = NULL;
if (!ExtensionTabUtil::GetTabById(
tab_id, GetProfile(), true, NULL, NULL, &contents, NULL)) {
error_ = extensions::ErrorUtils::FormatErrorMessage(
extensions::tabs_constants::kTabNotFoundError,
base::IntToString(tab_id));
return NULL;
}
if (!contents) {
error_ = extensions::ErrorUtils::FormatErrorMessage(
"Web contents for tab not found",
base::IntToString(tab_id));
return NULL;
}
GURL expected_origin = contents->GetLastCommittedURL().GetOrigin();
if (expected_origin.spec() != security_origin) {
error_ = extensions::ErrorUtils::FormatErrorMessage(
"Invalid security origin. Expected=" + expected_origin.spec() +
", actual=" + security_origin,
base::IntToString(tab_id));
return NULL;
}
return contents->GetRenderProcessHost();
}
scoped_refptr<WebRtcLoggingHandlerHost>
WebrtcLoggingPrivateFunction::LoggingHandlerFromRequest(
const api::webrtc_logging_private::RequestInfo& request,
const std::string& security_origin) {
content::RenderProcessHost* host = RphFromRequest(request, security_origin);
if (!host)
return nullptr;
return base::UserDataAdapter<WebRtcLoggingHandlerHost>::Get(
host, WebRtcLoggingHandlerHost::kWebRtcLoggingHandlerHostKey);
}
scoped_refptr<WebRtcLoggingHandlerHost>
WebrtcLoggingPrivateFunctionWithGenericCallback::PrepareTask(
const RequestInfo& request, const std::string& security_origin,
WebRtcLoggingHandlerHost::GenericDoneCallback* callback) {
*callback = base::Bind(
&WebrtcLoggingPrivateFunctionWithGenericCallback::FireCallback, this);
return LoggingHandlerFromRequest(request, security_origin);
}
void WebrtcLoggingPrivateFunctionWithGenericCallback::FireCallback(
bool success, const std::string& error_message) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!success)
SetError(error_message);
SendResponse(success);
}
void WebrtcLoggingPrivateFunctionWithUploadCallback::FireCallback(
bool success, const std::string& report_id,
const std::string& error_message) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (success) {
api::webrtc_logging_private::UploadResult result;
result.report_id = report_id;
SetResult(result.ToValue());
} else {
SetError(error_message);
}
SendResponse(success);
}
void WebrtcLoggingPrivateFunctionWithRecordingDoneCallback::FireErrorCallback(
const std::string& error_message) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
SetError(error_message);
SendResponse(false);
}
void WebrtcLoggingPrivateFunctionWithRecordingDoneCallback::FireCallback(
const std::string& prefix_path,
bool did_stop,
bool did_manual_stop) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
api::webrtc_logging_private::RecordingInfo result;
result.prefix_path = prefix_path;
result.did_stop = did_stop;
result.did_manual_stop = did_manual_stop;
SetResult(result.ToValue());
SendResponse(true);
}
bool WebrtcLoggingPrivateSetMetaDataFunction::RunAsync() {
std::unique_ptr<SetMetaData::Params> params(
SetMetaData::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingHandlerHost::GenericDoneCallback callback;
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host =
PrepareTask(params->request, params->security_origin, &callback);
if (!webrtc_logging_handler_host.get())
return false;
std::unique_ptr<MetaDataMap> meta_data(new MetaDataMap());
for (const MetaDataEntry& entry : params->meta_data)
(*meta_data.get())[entry.key] = entry.value;
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&WebRtcLoggingHandlerHost::SetMetaData, webrtc_logging_handler_host,
base::Passed(&meta_data), callback));
return true;
}
bool WebrtcLoggingPrivateStartFunction::RunAsync() {
std::unique_ptr<Start::Params> params(Start::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingHandlerHost::GenericDoneCallback callback;
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host =
PrepareTask(params->request, params->security_origin, &callback);
if (!webrtc_logging_handler_host.get())
return false;
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&WebRtcLoggingHandlerHost::StartLogging, webrtc_logging_handler_host,
callback));
return true;
}
bool WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::RunAsync() {
std::unique_ptr<SetUploadOnRenderClose::Params> params(
SetUploadOnRenderClose::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host(
LoggingHandlerFromRequest(params->request, params->security_origin));
if (!webrtc_logging_handler_host.get())
return false;
webrtc_logging_handler_host->set_upload_log_on_render_close(
params->should_upload);
return true;
}
bool WebrtcLoggingPrivateStopFunction::RunAsync() {
std::unique_ptr<Stop::Params> params(Stop::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingHandlerHost::GenericDoneCallback callback;
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host =
PrepareTask(params->request, params->security_origin, &callback);
if (!webrtc_logging_handler_host.get())
return false;
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&WebRtcLoggingHandlerHost::StopLogging, webrtc_logging_handler_host,
callback));
return true;
}
bool WebrtcLoggingPrivateStoreFunction::RunAsync() {
std::unique_ptr<Store::Params> params(Store::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingHandlerHost::GenericDoneCallback callback;
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host =
PrepareTask(params->request, params->security_origin, &callback);
if (!webrtc_logging_handler_host.get())
return false;
const std::string local_log_id(HashIdWithOrigin(params->security_origin,
params->log_id));
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&WebRtcLoggingHandlerHost::StoreLog,
webrtc_logging_handler_host, local_log_id, callback));
return true;
}
bool WebrtcLoggingPrivateUploadStoredFunction::RunAsync() {
std::unique_ptr<UploadStored::Params> params(
UploadStored::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
scoped_refptr<WebRtcLoggingHandlerHost> logging_handler(
LoggingHandlerFromRequest(params->request, params->security_origin));
if (!logging_handler.get())
return false;
WebRtcLoggingHandlerHost::UploadDoneCallback callback = base::Bind(
&WebrtcLoggingPrivateUploadStoredFunction::FireCallback, this);
const std::string local_log_id(HashIdWithOrigin(params->security_origin,
params->log_id));
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&WebRtcLoggingHandlerHost::UploadStoredLog, logging_handler, local_log_id,
callback));
return true;
}
bool WebrtcLoggingPrivateUploadFunction::RunAsync() {
std::unique_ptr<Upload::Params> params(Upload::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
scoped_refptr<WebRtcLoggingHandlerHost> logging_handler(
LoggingHandlerFromRequest(params->request, params->security_origin));
if (!logging_handler.get())
return false;
WebRtcLoggingHandlerHost::UploadDoneCallback callback = base::Bind(
&WebrtcLoggingPrivateUploadFunction::FireCallback, this);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&WebRtcLoggingHandlerHost::UploadLog, logging_handler, callback));
return true;
}
bool WebrtcLoggingPrivateDiscardFunction::RunAsync() {
std::unique_ptr<Discard::Params> params(Discard::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingHandlerHost::GenericDoneCallback callback;
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host =
PrepareTask(params->request, params->security_origin, &callback);
if (!webrtc_logging_handler_host.get())
return false;
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&WebRtcLoggingHandlerHost::DiscardLog, webrtc_logging_handler_host,
callback));
return true;
}
bool WebrtcLoggingPrivateStartRtpDumpFunction::RunAsync() {
std::unique_ptr<StartRtpDump::Params> params(
StartRtpDump::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
if (!params->incoming && !params->outgoing) {
FireCallback(false, "Either incoming or outgoing must be true.");
return true;
}
RtpDumpType type =
(params->incoming && params->outgoing)
? RTP_DUMP_BOTH
: (params->incoming ? RTP_DUMP_INCOMING : RTP_DUMP_OUTGOING);
content::RenderProcessHost* host =
RphFromRequest(params->request, params->security_origin);
if (!host)
return false;
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host(
base::UserDataAdapter<WebRtcLoggingHandlerHost>::Get(
host, WebRtcLoggingHandlerHost::kWebRtcLoggingHandlerHostKey));
WebRtcLoggingHandlerHost::GenericDoneCallback callback = base::Bind(
&WebrtcLoggingPrivateStartRtpDumpFunction::FireCallback, this);
// This call cannot fail.
content::RenderProcessHost::WebRtcStopRtpDumpCallback stop_callback =
host->StartRtpDump(params->incoming,
params->outgoing,
base::Bind(&WebRtcLoggingHandlerHost::OnRtpPacket,
webrtc_logging_handler_host));
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&WebRtcLoggingHandlerHost::StartRtpDump,
webrtc_logging_handler_host,
type,
callback,
stop_callback));
return true;
}
bool WebrtcLoggingPrivateStopRtpDumpFunction::RunAsync() {
std::unique_ptr<StopRtpDump::Params> params(
StopRtpDump::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
if (!params->incoming && !params->outgoing) {
FireCallback(false, "Either incoming or outgoing must be true.");
return true;
}
RtpDumpType type =
(params->incoming && params->outgoing)
? RTP_DUMP_BOTH
: (params->incoming ? RTP_DUMP_INCOMING : RTP_DUMP_OUTGOING);
content::RenderProcessHost* host =
RphFromRequest(params->request, params->security_origin);
if (!host)
return false;
scoped_refptr<WebRtcLoggingHandlerHost> webrtc_logging_handler_host(
base::UserDataAdapter<WebRtcLoggingHandlerHost>::Get(
host, WebRtcLoggingHandlerHost::kWebRtcLoggingHandlerHostKey));
WebRtcLoggingHandlerHost::GenericDoneCallback callback = base::Bind(
&WebrtcLoggingPrivateStopRtpDumpFunction::FireCallback, this);
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&WebRtcLoggingHandlerHost::StopRtpDump,
webrtc_logging_handler_host,
type,
callback));
return true;
}
bool WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::RunAsync() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAudioDebugRecordingsFromExtension)) {
return false;
}
std::unique_ptr<StartAudioDebugRecordings::Params> params(
StartAudioDebugRecordings::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
if (params->seconds < 0) {
FireErrorCallback("seconds must be greater than or equal to 0");
return true;
}
content::RenderProcessHost* host =
RphFromRequest(params->request, params->security_origin);
if (!host)
return false;
scoped_refptr<AudioDebugRecordingsHandler> audio_debug_recordings_handler(
base::UserDataAdapter<AudioDebugRecordingsHandler>::Get(
host, AudioDebugRecordingsHandler::kAudioDebugRecordingsHandlerKey));
audio_debug_recordings_handler->StartAudioDebugRecordings(
host, base::TimeDelta::FromSeconds(params->seconds),
base::Bind(
&WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::FireCallback,
this),
base::Bind(&WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::
FireErrorCallback,
this));
return true;
}
bool WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::RunAsync() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAudioDebugRecordingsFromExtension)) {
return false;
}
std::unique_ptr<StopAudioDebugRecordings::Params> params(
StopAudioDebugRecordings::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
content::RenderProcessHost* host =
RphFromRequest(params->request, params->security_origin);
if (!host)
return false;
scoped_refptr<AudioDebugRecordingsHandler> audio_debug_recordings_handler(
base::UserDataAdapter<AudioDebugRecordingsHandler>::Get(
host, AudioDebugRecordingsHandler::kAudioDebugRecordingsHandlerKey));
audio_debug_recordings_handler->StopAudioDebugRecordings(
host,
base::Bind(
&WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::FireCallback,
this),
base::Bind(&WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::
FireErrorCallback,
this));
return true;
}
bool WebrtcLoggingPrivateStartWebRtcEventLoggingFunction::RunAsync() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebRtcEventLoggingFromExtension)) {
return false;
}
std::unique_ptr<StartWebRtcEventLogging::Params> params(
StartWebRtcEventLogging::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
if (params->seconds < 0) {
FireErrorCallback("seconds must be greater than or equal to 0");
return true;
}
content::RenderProcessHost* host =
RphFromRequest(params->request, params->security_origin);
if (!host)
return false;
scoped_refptr<WebRtcEventLogHandler> webrtc_event_log_handler(
base::UserDataAdapter<WebRtcEventLogHandler>::Get(
host, WebRtcEventLogHandler::kWebRtcEventLogHandlerKey));
webrtc_event_log_handler->StartWebRtcEventLogging(
host, base::TimeDelta::FromSeconds(params->seconds),
base::Bind(
&WebrtcLoggingPrivateStartWebRtcEventLoggingFunction::FireCallback,
this),
base::Bind(
&WebrtcLoggingPrivateStartWebRtcEventLoggingFunction::FireErrorCallback,
this));
return true;
}
bool WebrtcLoggingPrivateStopWebRtcEventLoggingFunction::RunAsync() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebRtcEventLoggingFromExtension)) {
return false;
}
std::unique_ptr<StopWebRtcEventLogging::Params> params(
StopWebRtcEventLogging::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
content::RenderProcessHost* host =
RphFromRequest(params->request, params->security_origin);
if (!host)
return false;
scoped_refptr<WebRtcEventLogHandler> webrtc_event_log_handler(
base::UserDataAdapter<WebRtcEventLogHandler>::Get(
host, WebRtcEventLogHandler::kWebRtcEventLogHandlerKey));
webrtc_event_log_handler->StopWebRtcEventLogging(
host,
base::Bind(
&WebrtcLoggingPrivateStopWebRtcEventLoggingFunction::FireCallback,
this),
base::Bind(
&WebrtcLoggingPrivateStopWebRtcEventLoggingFunction::FireErrorCallback,
this));
return true;
}
} // namespace extensions