diff options
| author | guidou <guidou@chromium.org> | 2015-12-18 19:11:03 -0800 |
|---|---|---|
| committer | Commit bot <commit-bot@chromium.org> | 2015-12-19 03:12:10 +0000 |
| commit | 19d3df7ad0956e8ac2f366c67957603ca06ff1cf (patch) | |
| tree | f005186e327bda1d62b2a3e2add62308586dcaaf | |
| parent | bcd89d9973489ca59b4433edd5db680dae12b73c (diff) | |
| download | chromium_src-19d3df7ad0956e8ac2f366c67957603ca06ff1cf.zip chromium_src-19d3df7ad0956e8ac2f366c67957603ca06ff1cf.tar.gz chromium_src-19d3df7ad0956e8ac2f366c67957603ca06ff1cf.tar.bz2 | |
Allow diagnostic audio recordings (AEC dumps) through a private API extension protected behind a flag.
TBR=grunell@chromium.org
BUG=568169
Review URL: https://codereview.chromium.org/1530863002
Cr-Commit-Position: refs/heads/master@{#366258}
13 files changed, 390 insertions, 4 deletions
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc index cefad21..a1387ea 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc @@ -4,6 +4,7 @@ #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" @@ -11,6 +12,7 @@ #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" @@ -36,6 +38,10 @@ 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 { std::string HashIdWithOrigin(const std::string& security_origin, @@ -124,6 +130,26 @@ void WebrtcLoggingPrivateFunctionWithUploadCallback::FireCallback( SendResponse(success); } +void WebrtcLoggingPrivateFunctionWithAudioDebugRecordingsCallback:: + FireErrorCallback(const std::string& error_message) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + SetError(error_message); + SendResponse(false); +} + +void WebrtcLoggingPrivateFunctionWithAudioDebugRecordingsCallback::FireCallback( + const std::string& prefix_path, + bool did_stop, + bool did_manual_stop) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + api::webrtc_logging_private::AudioDebugRecordingsInfo result; + result.prefix_path = prefix_path; + result.did_stop = did_stop; + result.did_manual_stop = did_manual_stop; + SetResult(result.ToValue().release()); + SendResponse(true); +} + bool WebrtcLoggingPrivateSetMetaDataFunction::RunAsync() { scoped_ptr<SetMetaData::Params> params(SetMetaData::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); @@ -348,4 +374,67 @@ bool WebrtcLoggingPrivateStopRtpDumpFunction::RunAsync() { return true; } +bool WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::RunAsync() { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableAudioDebugRecordingsFromExtension)) { + return false; + } + + scoped_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<WebRtcLoggingHandlerHost> webrtc_logging_handler_host( + base::UserDataAdapter<WebRtcLoggingHandlerHost>::Get(host, host)); + + webrtc_logging_handler_host->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; + } + + scoped_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<WebRtcLoggingHandlerHost> webrtc_logging_handler_host( + base::UserDataAdapter<WebRtcLoggingHandlerHost>::Get(host, host)); + + webrtc_logging_handler_host->StopAudioDebugRecordings( + host, + base::Bind( + &WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::FireCallback, + this), + base::Bind(&WebrtcLoggingPrivateStopAudioDebugRecordingsFunction:: + FireErrorCallback, + this)); + return true; +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h index 202c727..ff5553b 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h @@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_WEBRTC_LOGGING_PRIVATE_WEBRTC_LOGGING_PRIVATE_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_WEBRTC_LOGGING_PRIVATE_WEBRTC_LOGGING_PRIVATE_API_H_ +#include <string> + #include "chrome/browser/extensions/chrome_extension_function.h" #if defined(ENABLE_WEBRTC) #include "chrome/browser/media/webrtc_logging_handler_host.h" @@ -69,6 +71,20 @@ class WebrtcLoggingPrivateFunctionWithUploadCallback #endif }; +class WebrtcLoggingPrivateFunctionWithAudioDebugRecordingsCallback + : public WebrtcLoggingPrivateFunction { + protected: + ~WebrtcLoggingPrivateFunctionWithAudioDebugRecordingsCallback() override {} + +#if defined(ENABLE_WEBRTC) + // Must be called on UI thread. + void FireErrorCallback(const std::string& error_message); + void FireCallback(const std::string& prefix_path, + bool did_stop, + bool did_manual_stop); +#endif +}; + class WebrtcLoggingPrivateSetMetaDataFunction : public WebrtcLoggingPrivateFunctionWithGenericCallback { public: @@ -209,6 +225,34 @@ class WebrtcLoggingPrivateStopRtpDumpFunction bool RunAsync() override; }; +class WebrtcLoggingPrivateStartAudioDebugRecordingsFunction + : public WebrtcLoggingPrivateFunctionWithAudioDebugRecordingsCallback { + public: + DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.startAudioDebugRecordings", + WEBRTCLOGGINGPRIVATE_STARTAUDIODEBUGRECORDINGS) + WebrtcLoggingPrivateStartAudioDebugRecordingsFunction() {} + + private: + ~WebrtcLoggingPrivateStartAudioDebugRecordingsFunction() override {} + + // ExtensionFunction overrides. + bool RunAsync() override; +}; + +class WebrtcLoggingPrivateStopAudioDebugRecordingsFunction + : public WebrtcLoggingPrivateFunctionWithAudioDebugRecordingsCallback { + public: + DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.stopAudioDebugRecordings", + WEBRTCLOGGINGPRIVATE_STOPAUDIODEBUGRECORDINGS) + WebrtcLoggingPrivateStopAudioDebugRecordingsFunction() {} + + private: + ~WebrtcLoggingPrivateStopAudioDebugRecordingsFunction() override {} + + // ExtensionFunction overrides. + bool RunAsync() override; +}; + } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_WEBRTC_LOGGING_PRIVATE_WEBRTC_LOGGING_PRIVATE_API_H_ diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc index 836e06b..256321e 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc @@ -74,4 +74,16 @@ bool WebrtcLoggingPrivateStopRtpDumpFunction::RunAsync() { return false; } +bool WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::RunAsync() { + SetError(kErrorNotSupported); + SendResponse(false); + return false; +} + +bool WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::RunAsync() { + SetError(kErrorNotSupported); + SendResponse(false); + return false; +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc index 835e172..b47e8c1 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc @@ -12,6 +12,7 @@ #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/media/webrtc_log_uploader.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_switches.h" #include "components/compression/compression_utils.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" @@ -28,6 +29,8 @@ using extensions::WebrtcLoggingPrivateStopRtpDumpFunction; using extensions::WebrtcLoggingPrivateStoreFunction; using extensions::WebrtcLoggingPrivateUploadFunction; using extensions::WebrtcLoggingPrivateUploadStoredFunction; +using extensions::WebrtcLoggingPrivateStartAudioDebugRecordingsFunction; +using extensions::WebrtcLoggingPrivateStopAudioDebugRecordingsFunction; namespace utils = extension_function_test_utils; @@ -58,7 +61,6 @@ void InitializeTestMetaData(base::ListValue* parameters) { class WebrtcLoggingPrivateApiTest : public ExtensionApiTest { protected: - void SetUp() override { ExtensionApiTest::SetUp(); extension_ = extensions::test_util::CreateEmptyExtension(); @@ -162,6 +164,21 @@ class WebrtcLoggingPrivateApiTest : public ExtensionApiTest { return RunFunction<WebrtcLoggingPrivateUploadStoredFunction>(params, true); } + bool StartAudioDebugRecordings(int seconds) { + base::ListValue params; + AppendTabIdAndUrl(¶ms); + params.AppendInteger(seconds); + return RunFunction<WebrtcLoggingPrivateStartAudioDebugRecordingsFunction>( + params, true); + } + + bool StopAudioDebugRecordings() { + base::ListValue params; + AppendTabIdAndUrl(¶ms); + return RunFunction<WebrtcLoggingPrivateStopAudioDebugRecordingsFunction>( + params, true); + } + private: scoped_refptr<Extension> extension_; }; @@ -407,3 +424,20 @@ IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest, buffer_override.multipart().find(kTestLoggingUrl)); } +IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest, + TestStartStopAudioDebugRecordings) { + // TODO(guidou): These tests are missing verification of the actual AEC dump + // data. This will be fixed with a separate browser test. + // See crbug.com/569957. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableAudioDebugRecordingsFromExtension); + ASSERT_TRUE(StartAudioDebugRecordings(0)); + ASSERT_TRUE(StopAudioDebugRecordings()); +} + +IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest, + TestStartTimedAudioDebugRecordings) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableAudioDebugRecordingsFromExtension); + ASSERT_TRUE(StartAudioDebugRecordings(1)); +} diff --git a/chrome/browser/media/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc_logging_handler_host.cc index ef7dc19..daa0acc 100644 --- a/chrome/browser/media/webrtc_logging_handler_host.cc +++ b/chrome/browser/media/webrtc_logging_handler_host.cc @@ -105,6 +105,15 @@ void FormatMetaDataAsLogMessage( message->resize(message->size() - 1); } +// Returns a path name to be used as prefix for audio debug recordings files. +base::FilePath GetAudioDebugRecordingsPrefixPath( + const base::FilePath& directory, + uint64_t audio_debug_recordings_id) { + static const char kAudioDebugRecordingsFilePrefix[] = "AudioDebugRecordings."; + return directory.AppendASCII(kAudioDebugRecordingsFilePrefix + + base::Int64ToString(audio_debug_recordings_id)); +} + } // namespace WebRtcLogBuffer::WebRtcLogBuffer() @@ -141,12 +150,15 @@ void WebRtcLogBuffer::SetComplete() { } WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost( - Profile* profile, WebRtcLogUploader* log_uploader) + Profile* profile, + WebRtcLogUploader* log_uploader) : BrowserMessageFilter(WebRtcLoggingMsgStart), profile_(profile), logging_state_(CLOSED), upload_log_on_render_close_(false), - log_uploader_(log_uploader) { + log_uploader_(log_uploader), + is_audio_debug_recordings_in_progress_(false), + current_audio_debug_recordings_id_(0) { DCHECK(profile_); DCHECK(log_uploader_); } @@ -429,6 +441,35 @@ void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread( } } +void WebRtcLoggingHandlerHost::StartAudioDebugRecordings( + content::RenderProcessHost* host, + base::TimeDelta delay, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::FILE, FROM_HERE, + base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, + this), + base::Bind(&WebRtcLoggingHandlerHost::DoStartAudioDebugRecordings, this, + host, delay, callback, error_callback)); +} + +void WebRtcLoggingHandlerHost::StopAudioDebugRecordings( + content::RenderProcessHost* host, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::FILE, FROM_HERE, + base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, + this), + base::Bind(&WebRtcLoggingHandlerHost::DoStopAudioDebugRecordings, this, + host, true /* manual stop */, + current_audio_debug_recordings_id_, callback, error_callback)); +} + void WebRtcLoggingHandlerHost::OnChannelClosing() { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ == STARTED || logging_state_ == STOPPED) { @@ -765,3 +806,68 @@ void WebRtcLoggingHandlerHost::FireGenericDoneCallback( FROM_HERE, base::Bind(callback, success, error_message_with_state)); } + +void WebRtcLoggingHandlerHost::DoStartAudioDebugRecordings( + content::RenderProcessHost* host, + base::TimeDelta delay, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback, + const base::FilePath& log_directory) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (is_audio_debug_recordings_in_progress_) { + error_callback.Run("Audio debug recordings already in progress"); + return; + } + + is_audio_debug_recordings_in_progress_ = true; + base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath( + log_directory, ++current_audio_debug_recordings_id_); + host->EnableAudioDebugRecordings(prefix_path); + + if (delay.is_zero()) { + callback.Run(prefix_path.AsUTF8Unsafe(), false /* not stopped */, + false /* not manually stopped */); + return; + } + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&WebRtcLoggingHandlerHost::DoStopAudioDebugRecordings, this, + host, false /* no manual stop */, + current_audio_debug_recordings_id_, callback, error_callback, + prefix_path)); +} + +void WebRtcLoggingHandlerHost::DoStopAudioDebugRecordings( + content::RenderProcessHost* host, + bool is_manual_stop, + uint64_t audio_debug_recordings_id, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback, + const base::FilePath& log_directory) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK_LE(audio_debug_recordings_id, current_audio_debug_recordings_id_); + + base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath( + log_directory, audio_debug_recordings_id); + // Prevent an old posted StopAudioDebugRecordings() call to stop a newer dump. + // This could happen in a sequence like: + // Start(10); //Start dump 1. Post Stop() to run after 10 seconds. + // Stop(); // Manually stop dump 1 before 10 seconds; + // Start(20); // Start dump 2. Posted Stop() for 1 should not stop dump 2. + if (audio_debug_recordings_id < current_audio_debug_recordings_id_) { + callback.Run(prefix_path.AsUTF8Unsafe(), false /* not stopped */, + is_manual_stop); + return; + } + + if (!is_audio_debug_recordings_in_progress_) { + error_callback.Run("No audio debug recording in progress"); + return; + } + + host->DisableAudioDebugRecordings(); + is_audio_debug_recordings_in_progress_ = false; + callback.Run(prefix_path.AsUTF8Unsafe(), true /* stopped */, is_manual_stop); +} diff --git a/chrome/browser/media/webrtc_logging_handler_host.h b/chrome/browser/media/webrtc_logging_handler_host.h index c2b3e32..d62d6cc 100644 --- a/chrome/browser/media/webrtc_logging_handler_host.h +++ b/chrome/browser/media/webrtc_logging_handler_host.h @@ -77,6 +77,10 @@ class WebRtcLoggingHandlerHost : public content::BrowserMessageFilter { typedef base::Callback<void(bool, const std::string&)> GenericDoneCallback; typedef base::Callback<void(bool, const std::string&, const std::string&)> UploadDoneCallback; + typedef base::Callback<void(const std::string&)> + AudioDebugRecordingsErrorCallback; + typedef base::Callback<void(const std::string&, bool, bool)> + AudioDebugRecordingsCallback; WebRtcLoggingHandlerHost(Profile* profile, WebRtcLogUploader* log_uploader); @@ -146,6 +150,27 @@ class WebRtcLoggingHandlerHost : public content::BrowserMessageFilter { size_t packet_length, bool incoming); + // Starts an audio debug recording. The recording lasts the given |delay|, + // unless |delay| is zero, in which case recording will continue until + // StopAudioDebugRecordings() is explicitly invoked. + // |callback| is invoked once recording stops. If |delay| is zero + // |callback| is invoked once recording starts. + // If a recording was already in progress, |error_callback| is invoked instead + // of |callback|. + void StartAudioDebugRecordings( + content::RenderProcessHost* host, + base::TimeDelta delay, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback); + + // Stops an audio debug recording. |callback| is invoked once recording + // stops. If no recording was in progress, |error_callback| is invoked instead + // of |callback|. + void StopAudioDebugRecordings( + content::RenderProcessHost* host, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback); + private: // States used for protecting from function calls made at non-allowed points // in time. For example, StartLogging() is only allowed in CLOSED state. @@ -232,6 +257,23 @@ class WebRtcLoggingHandlerHost : public content::BrowserMessageFilter { bool success, const std::string& error_message); + // Helper for starting audio debug recordings. + void DoStartAudioDebugRecordings( + content::RenderProcessHost* host, + base::TimeDelta delay, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback, + const base::FilePath& log_directory); + + // Helper for stopping audio debug recordings. + void DoStopAudioDebugRecordings( + content::RenderProcessHost* host, + bool is_manual_stop, + uint64_t audio_debug_recordings_id, + const AudioDebugRecordingsCallback& callback, + const AudioDebugRecordingsErrorCallback& error_callback, + const base::FilePath& log_directory); + scoped_ptr<WebRtcLogBuffer> log_buffer_; // The profile associated with our renderer process. @@ -273,6 +315,12 @@ class WebRtcLoggingHandlerHost : public content::BrowserMessageFilter { // Ownership lies with the browser process. WebRtcLogUploader* const log_uploader_; + // Must be accessed on the UI thread. + bool is_audio_debug_recordings_in_progress_; + + // This counter allows saving each debug recording in separate files. + uint64_t current_audio_debug_recordings_id_; + DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingHandlerHost); }; diff --git a/chrome/browser/resources/hangout_services/manifest.json b/chrome/browser/resources/hangout_services/manifest.json index 211426e..92255eb 100644 --- a/chrome/browser/resources/hangout_services/manifest.json +++ b/chrome/browser/resources/hangout_services/manifest.json @@ -5,7 +5,7 @@ "name": "Google Hangouts", // Note: Always update the version number when this file is updated. Chrome // triggers extension preferences update on the version increase. - "version": "1.1.2", + "version": "1.2.0", "manifest_version": 2, "externally_connectable": { "matches": [ diff --git a/chrome/browser/resources/hangout_services/thunk.js b/chrome/browser/resources/hangout_services/thunk.js index d03a831..dd24d6f 100644 --- a/chrome/browser/resources/hangout_services/thunk.js +++ b/chrome/browser/resources/hangout_services/thunk.js @@ -167,6 +167,14 @@ chrome.runtime.onMessageExternal.addListener( chrome.webrtcLoggingPrivate.stopRtpDump( requestInfo, origin, incoming, outgoing, doSendResponse); return true; + } else if (method == 'logging.startAudioDebugRecordings') { + var seconds = message['seconds'] || 0; + chrome.webrtcLoggingPrivate.startAudioDebugRecordings( + seconds, doSendResponse); + return true; + } else if (method == 'logging.stopAudioDebugRecordings') { + chrome.webrtcLoggingPrivate.stopAudioDebugRecordings(doSendResponse); + return true; } throw new Error('Unknown method: ' + method); } catch (e) { diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index c9c92498..7b7bbbc 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -375,6 +375,10 @@ const char kEnableAddToShelf[] = "enable-add-to-shelf"; // Enable OS integration for Chrome app file associations. const char kEnableAppsFileAssociations[] = "enable-apps-file-associations"; +// If the WebRTC logging private API is active, enables audio debug recordings. +const char kEnableAudioDebugRecordingsFromExtension[] = + "enable-audio-debug-recordings-from-extension"; + // Enables the benchmarking extensions. const char kEnableBenchmarking[] = "enable-benchmarking"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 22914f1..81a368c 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -109,6 +109,7 @@ extern const char kDumpBrowserHistograms[]; extern const char kEasyUnlockAppPath[]; extern const char kEnableAddToShelf[]; extern const char kEnableAppsFileAssociations[]; +extern const char kEnableAudioDebugRecordingsFromExtension[]; extern const char kEnableBenchmarking[]; extern const char kEnableBookmarkUndo[]; extern const char kEnableChildAccountDetection[]; diff --git a/chrome/common/extensions/api/webrtc_logging_private.idl b/chrome/common/extensions/api/webrtc_logging_private.idl index 5c72c95..0f900f9 100644 --- a/chrome/common/extensions/api/webrtc_logging_private.idl +++ b/chrome/common/extensions/api/webrtc_logging_private.idl @@ -28,7 +28,23 @@ namespace webrtcLoggingPrivate { long? guestProcessId; }; + // This contains information about the result of audio debug recordings. + dictionary AudioDebugRecordingsInfo { + // Absolute path prefix for the files with the audio debug recordings. + DOMString prefixPath; + + // Indicates if recording was stopped. + boolean didStop; + + // Indicates if recording was stopped manually through a + // stopAudioDebugRecordings() call. + boolean didManualStop; + }; + + callback GenericDoneCallback = void (); + callback AudioDebugRecordingsCallback = + void (AudioDebugRecordingsInfo info); callback UploadDoneCallback = void (UploadResult result); interface Functions { @@ -111,5 +127,25 @@ namespace webrtcLoggingPrivate { boolean incoming, boolean outgoing, GenericDoneCallback callback); + + // Starts audio debug recordings. + // |seconds| indicates how many seconds of audio to record. |callback| + // is invoked once recording stops. + // If |seconds| is zero, recording will continue until + // stopAudioDebugRecordings() is explicitly called. In this case, + // |callback| is invoked once recording starts and will report + // that recording has not stopped. + // If |seconds| is negative, startAudioDebugRecordings() fails. + static void startAudioDebugRecordings(RequestInfo request, + DOMString securityOrigin, + long seconds, + AudioDebugRecordingsCallback callback); + + // Stops audio debug recordings. |callback| is invoked once recording + // stops. If there is no recording in progress, stopAudioDebugRecordings() + // fails. + static void stopAudioDebugRecordings(RequestInfo request, + DOMString securityOrigin, + AudioDebugRecordingsCallback callback); }; }; diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 7820b7f..588b05e 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -1158,6 +1158,8 @@ enum HistogramValue { BLUETOOTHPRIVATE_FORGETDEVICE, DISPLAYSOURCE_GETAVAILABLESINKS, DISPLAYSOURCE_REQUESTAUTHENTICATION, + WEBRTCLOGGINGPRIVATE_STARTAUDIODEBUGRECORDINGS, + WEBRTCLOGGINGPRIVATE_STOPAUDIODEBUGRECORDINGS, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 20fafda..3fe2253 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -62793,6 +62793,8 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. <int value="1097" label="BLUETOOTHPRIVATE_FORGETDEVICE"/> <int value="1098" label="DISPLAYSOURCE_GETAVAILABLESINKS"/> <int value="1099" label="DISPLAYSOURCE_REQUESTAUTHENTICATION"/> + <int value="1100" label="WEBRTCLOGGINGPRIVATE_STARTAUDIODEBUGRECORDINGS"/> + <int value="1101" label="WEBRTCLOGGINGPRIVATE_STOPAUDIODEBUGRECORDINGS"/> </enum> <enum name="ExtensionInstallCause" type="int"> |
