diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-05-09 14:22:11 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-05-09 15:11:45 +0000 |
commit | 2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch) | |
tree | e75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/chromecast/base | |
parent | a4f3d46271c57e8155ba912df46a05559d14726e (diff) | |
download | qtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz |
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion.
Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/chromecast/base')
29 files changed, 1775 insertions, 169 deletions
diff --git a/chromium/chromecast/base/BUILD.gn b/chromium/chromecast/base/BUILD.gn index 355c0da7fe1..c5a54457d0d 100644 --- a/chromium/chromecast/base/BUILD.gn +++ b/chromium/chromecast/base/BUILD.gn @@ -6,6 +6,23 @@ import("//chrome/version.gni") # TODO layering violation! import("//chromecast/chromecast.gni") import("//testing/test.gni") +if (is_android) { + import("//build/config/android/rules.gni") +} + +declare_args() { + # Denotes the type of Cast product. This is #defined as CAST_PRODUCT_TYPE in + # version.h. This is an integer in the range [0-4]. + cast_product_type = 0 + + # If true, IS_CAST_DEBUG_BUILD() will evaluate to 1 in version.h. Otherwise, + # it will evaluate to 0. Overriding this when is_debug=false is useful for + # doing engineering builds. + cast_is_debug = is_debug +} + +assert(cast_product_type >= 0 && cast_product_type <= 4) + # GYP target: chromecast.gyp:cast_base source_set("base") { sources = [ @@ -20,6 +37,8 @@ source_set("base") { "cast_paths.h", "cast_resource.cc", "cast_resource.h", + "chromecast_config_android.cc", + "chromecast_config_android.h", "chromecast_switches.cc", "chromecast_switches.h", "device_capabilities.h", @@ -49,6 +68,10 @@ source_set("base") { deps = [ "//base", ] + + if (is_android) { + deps += [ ":jni_headers" ] + } } # GYP target: n/a @@ -68,6 +91,7 @@ source_set("test_support") { test("cast_base_unittests") { sources = [ "bind_to_task_runner_unittest.cc", + "chromecast_switches_unittest.cc", "device_capabilities_impl_unittest.cc", "error_codes_unittest.cc", "path_utils_unittest.cc", @@ -87,38 +111,101 @@ test("cast_base_unittests") { source_set("cast_sys_info") { sources = [ + "cast_sys_info_android.cc", + "cast_sys_info_android.h", "cast_sys_info_dummy.cc", "cast_sys_info_dummy.h", "cast_sys_info_util.h", ] - if (chromecast_branding == "public" && !is_android) { + deps = [ + "//base", + "//chromecast/public", + ] + + if (is_android) { + deps += [ + ":cast_version", + "//chromecast/browser:jni_headers", + ] + } else if (chromecast_branding == "public") { sources += [ "cast_sys_info_util_simple.cc" ] } +} - # TODO(mbjorge): put cast_sys_info_android in here +# This target runs a script which generates a file containing key-value pairs. +# //build/util/version.py will parse this file, creating "version.h". This +# target shall only be depended upon by ":cast_version". +action("generate_cast_version_params") { + visibility = [ ":cast_version_action" ] - deps = [ - "//base", - "//chromecast/public", + script = "//chromecast/tools/build/generate_cast_version_params.py" + + params_file = "$root_gen_dir/cast_version_params" + outputs = [ + params_file, + ] + + args = [ + "-o", + rebase_path(params_file), + "-p", + "$cast_product_type", ] + + if (cast_is_debug) { + args += [ "-d" ] + } + + if (chromecast_branding != "public") { + args += [ + "-r", + rebase_path("//chromecast/internal/build/cast_build_release"), + ] + } } process_version("cast_version") { template_file = "version.h.in" output = "$target_gen_dir/version.h" + + params_file = get_target_outputs(":generate_cast_version_params") + deps = [ + ":generate_cast_version_params", + ] + extra_args = [ "-e", "VERSION_FULL=\"%s.%s.%s.%s\"%(MAJOR,MINOR,BUILD,PATCH)", - - # TODO(slan): Populate the fields below with real values - "-e", - "CAST_BUILD_INCREMENTAL=20150608.181153", - "-e", - "CAST_BUILD_RELEASE=1.15", - "-e", - "CAST_IS_DEBUG_BUILD=1", - "-e", - "CAST_PRODUCT_TYPE=0", + "-f", + rebase_path(params_file[0]), ] } + +if (is_android) { + # GYP target: chromecast.gyp:jni_headers + generate_jni("jni_headers") { + sources = [ + "java/src/org/chromium/chromecast/base/ChromecastConfigAndroid.java", + "java/src/org/chromium/chromecast/base/DumpstateWriter.java", + "java/src/org/chromium/chromecast/base/SystemTimeChangeNotifierAndroid.java", + ] + + jni_package = "chromecast" + } + + # GYP target: chromecast.gyp:cast_base_java + android_library("base_java") { + java_src_dir = "//chromecast/base/java/src" + java_files = [ + "$java_src_dir/org/chromium/chromecast/base/CastSettingsManager.java", + "$java_src_dir/org/chromium/chromecast/base/ChromecastConfigAndroid.java", + "$java_src_dir/org/chromium/chromecast/base/DumpstateWriter.java", + "$java_src_dir/org/chromium/chromecast/base/SystemTimeChangeNotifierAndroid.java", + ] + + deps = [ + "//base:base_java", + ] + } +} diff --git a/chromium/chromecast/base/bind_to_task_runner.h b/chromium/chromecast/base/bind_to_task_runner.h index 822ced7d78b..8902be261a5 100644 --- a/chromium/chromecast/base/bind_to_task_runner.h +++ b/chromium/chromecast/base/bind_to_task_runner.h @@ -5,12 +5,13 @@ #ifndef CHROMECAST_BASE_BIND_TO_TASK_RUNNER_H_ #define CHROMECAST_BASE_BIND_TO_TASK_RUNNER_H_ +#include <memory> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" #include "base/location.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/task_runner.h" #include "base/thread_task_runner_handle.h" @@ -42,8 +43,8 @@ T& TrampolineForward(T& t) { } template <typename T, typename R> -base::internal::PassedWrapper<scoped_ptr<T, R>> TrampolineForward( - scoped_ptr<T, R>& p) { +base::internal::PassedWrapper<std::unique_ptr<T, R>> TrampolineForward( + std::unique_ptr<T, R>& p) { return base::Passed(&p); } diff --git a/chromium/chromecast/base/bind_to_task_runner_unittest.cc b/chromium/chromecast/base/bind_to_task_runner_unittest.cc index 240c8f961c6..b2148095147 100644 --- a/chromium/chromecast/base/bind_to_task_runner_unittest.cc +++ b/chromium/chromecast/base/bind_to_task_runner_unittest.cc @@ -6,6 +6,7 @@ #include <utility> +#include "base/memory/free_deleter.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,17 +17,17 @@ void BoundBoolSet(bool* var, bool val) { *var = val; } -void BoundBoolSetFromScopedPtr(bool* var, scoped_ptr<bool> val) { +void BoundBoolSetFromScopedPtr(bool* var, std::unique_ptr<bool> val) { *var = *val; } void BoundBoolSetFromScopedPtrFreeDeleter( bool* var, - scoped_ptr<bool, base::FreeDeleter> val) { - *var = val; + std::unique_ptr<bool, base::FreeDeleter> val) { + *var = *val; } -void BoundBoolSetFromScopedArray(bool* var, scoped_ptr<bool[]> val) { +void BoundBoolSetFromScopedArray(bool* var, std::unique_ptr<bool[]> val) { *var = val[0]; } @@ -69,7 +70,7 @@ TEST_F(BindToTaskRunnerTest, Bool) { TEST_F(BindToTaskRunnerTest, BoundScopedPtrBool) { bool bool_val = false; - scoped_ptr<bool> scoped_ptr_bool(new bool(true)); + std::unique_ptr<bool> scoped_ptr_bool(new bool(true)); base::Closure cb = BindToCurrentThread(base::Bind( &BoundBoolSetFromScopedPtr, &bool_val, base::Passed(&scoped_ptr_bool))); cb.Run(); @@ -80,8 +81,8 @@ TEST_F(BindToTaskRunnerTest, BoundScopedPtrBool) { TEST_F(BindToTaskRunnerTest, PassedScopedPtrBool) { bool bool_val = false; - scoped_ptr<bool> scoped_ptr_bool(new bool(true)); - base::Callback<void(scoped_ptr<bool>)> cb = + std::unique_ptr<bool> scoped_ptr_bool(new bool(true)); + base::Callback<void(std::unique_ptr<bool>)> cb = BindToCurrentThread(base::Bind(&BoundBoolSetFromScopedPtr, &bool_val)); cb.Run(std::move(scoped_ptr_bool)); EXPECT_FALSE(bool_val); @@ -91,7 +92,7 @@ TEST_F(BindToTaskRunnerTest, PassedScopedPtrBool) { TEST_F(BindToTaskRunnerTest, BoundScopedArrayBool) { bool bool_val = false; - scoped_ptr<bool[]> scoped_array_bool(new bool[1]); + std::unique_ptr<bool[]> scoped_array_bool(new bool[1]); scoped_array_bool[0] = true; base::Closure cb = BindToCurrentThread(base::Bind(&BoundBoolSetFromScopedArray, &bool_val, @@ -104,9 +105,9 @@ TEST_F(BindToTaskRunnerTest, BoundScopedArrayBool) { TEST_F(BindToTaskRunnerTest, PassedScopedArrayBool) { bool bool_val = false; - scoped_ptr<bool[]> scoped_array_bool(new bool[1]); + std::unique_ptr<bool[]> scoped_array_bool(new bool[1]); scoped_array_bool[0] = true; - base::Callback<void(scoped_ptr<bool[]>)> cb = + base::Callback<void(std::unique_ptr<bool[]>)> cb = BindToCurrentThread(base::Bind(&BoundBoolSetFromScopedArray, &bool_val)); cb.Run(std::move(scoped_array_bool)); EXPECT_FALSE(bool_val); @@ -116,7 +117,7 @@ TEST_F(BindToTaskRunnerTest, PassedScopedArrayBool) { TEST_F(BindToTaskRunnerTest, BoundScopedPtrFreeDeleterBool) { bool bool_val = false; - scoped_ptr<bool, base::FreeDeleter> scoped_ptr_free_deleter_bool( + std::unique_ptr<bool, base::FreeDeleter> scoped_ptr_free_deleter_bool( static_cast<bool*>(malloc(sizeof(bool)))); *scoped_ptr_free_deleter_bool = true; base::Closure cb = BindToCurrentThread( @@ -130,10 +131,10 @@ TEST_F(BindToTaskRunnerTest, BoundScopedPtrFreeDeleterBool) { TEST_F(BindToTaskRunnerTest, PassedScopedPtrFreeDeleterBool) { bool bool_val = false; - scoped_ptr<bool, base::FreeDeleter> scoped_ptr_free_deleter_bool( + std::unique_ptr<bool, base::FreeDeleter> scoped_ptr_free_deleter_bool( static_cast<bool*>(malloc(sizeof(bool)))); *scoped_ptr_free_deleter_bool = true; - base::Callback<void(scoped_ptr<bool, base::FreeDeleter>)> cb = + base::Callback<void(std::unique_ptr<bool, base::FreeDeleter>)> cb = BindToCurrentThread( base::Bind(&BoundBoolSetFromScopedPtrFreeDeleter, &bool_val)); cb.Run(std::move(scoped_ptr_free_deleter_bool)); diff --git a/chromium/chromecast/base/cast_resource.cc b/chromium/chromecast/base/cast_resource.cc index cbe9b51d7cd..7978d868fbd 100644 --- a/chromium/chromecast/base/cast_resource.cc +++ b/chromium/chromecast/base/cast_resource.cc @@ -10,9 +10,9 @@ void CastResource::SetCastResourceClient(Client* client) { client_ = client; } -void CastResource::NotifyResourceAcquired() { +void CastResource::RegisterWithClient() { if (client_) - client_->OnResourceAcquired(this); + client_->RegisterCastResource(this); } void CastResource::NotifyResourceReleased(Resource remain) { diff --git a/chromium/chromecast/base/cast_resource.h b/chromium/chromecast/base/cast_resource.h index cd248d77edc..67315ec392a 100644 --- a/chromium/chromecast/base/cast_resource.h +++ b/chromium/chromecast/base/cast_resource.h @@ -9,7 +9,13 @@ namespace chromecast { -// Interface for resources needed to run application. +// A CastResource is a user of 1 or more Resources (primary screen, audio, +// etc). As a user, it is responsible for doing any cast-specific component +// initialization when the Resources it uses are granted. This initialization +// is referred to as "acquiring" the Resources. Conversely, when the Resources +// it uses are revoked, it must deinitialize these cast-specific components. +// This deinitialization is referred to as "releasing" the Resources. +// TODO(maclellant): RENAME/DESIGN THIS CLASS IN COMING REFACTOR. class CastResource { public: // Resources necessary to run cast apps. CastResource may contain union of the @@ -33,11 +39,22 @@ class CastResource { (kResourceAudio | kResourceScreenPrimary | kResourceScreenSecondary), }; + // A Client is responsible for notifying all registered CastResource's when + // Resources are granted/revoked so that they can acquire/release those + // Resources. When a CastResource is done acquiring/releasing, it responds + // to the Client that it has completed. A Client can have multiple registered + // CastResource's, but each CastResouce has 1 Client that it responds to. class Client { public: - // Called when resource is created. CastResource should not be owned by - // Client. It can be called from any thread. - virtual void OnResourceAcquired(CastResource* cast_resource) = 0; + // Called to register a CastResource with a Client. After registering, a + // CastResource will start getting notified when to acquire/release + // Resources. The Client does not take ownership of |cast_resource|. It can + // be called from any thread. + virtual void RegisterCastResource(CastResource* cast_resource) = 0; + + // TODO(esum): Add OnResourceAcquired() here once AcquireResource is + // allowed to be asynchronous. + // Called when part or all resources are released. It can be called from any // thread. // |cast_resource| the CastResource that is released. The pointer may be @@ -52,7 +69,17 @@ class CastResource { virtual ~Client() {} }; + // Sets the Client for the CastResource to respond to when it is done with + // Acquire/ReleaseResource. void SetCastResourceClient(Client* client); + // Called to acquire resources after OEM has granted them, and before + // they start getting used by consumers. Implementation must be synchronous + // since consumers will start using the resource immediately afterwards. + // TODO(esum): We should allow this method to be asynchronous in case an + // implementer needs to make expensive calls and doesn't want to block the + // UI thread (b/26239576). For now, don't do anything expensive in your + // implementation; if you really need to, then this bug has to be resolved. + virtual void AcquireResource(Resource resource) = 0; // Called to release resources. Implementation should call // Client::OnResourceReleased when resource is released on its side. virtual void ReleaseResource(Resource resource) = 0; @@ -61,7 +88,9 @@ class CastResource { CastResource() : client_(nullptr) {} virtual ~CastResource() {} - void NotifyResourceAcquired(); + // For derived classes to register themselves with their Client through + // Client::RegisterCastResource. + void RegisterWithClient(); void NotifyResourceReleased(Resource remain); private: diff --git a/chromium/chromecast/base/cast_sys_info_android.cc b/chromium/chromecast/base/cast_sys_info_android.cc index 0d85a06ad82..80eaf933894 100644 --- a/chromium/chromecast/base/cast_sys_info_android.cc +++ b/chromium/chromecast/base/cast_sys_info_android.cc @@ -7,6 +7,7 @@ #include "base/android/build_info.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/sys_info.h" #include "chromecast/base/cast_sys_info_util.h" @@ -25,8 +26,8 @@ bool CastSysInfoAndroid::RegisterJni(JNIEnv* env) { } // static -scoped_ptr<CastSysInfo> CreateSysInfo() { - return make_scoped_ptr(new CastSysInfoAndroid()); +std::unique_ptr<CastSysInfo> CreateSysInfo() { + return base::WrapUnique(new CastSysInfoAndroid()); } CastSysInfoAndroid::CastSysInfoAndroid() diff --git a/chromium/chromecast/base/cast_sys_info_util.h b/chromium/chromecast/base/cast_sys_info_util.h index 05ca069d655..36979377fbe 100644 --- a/chromium/chromecast/base/cast_sys_info_util.h +++ b/chromium/chromecast/base/cast_sys_info_util.h @@ -5,16 +5,16 @@ #ifndef CHROMECAST_BASE_CAST_SYS_INFO_UTIL_H_ #define CHROMECAST_BASE_CAST_SYS_INFO_UTIL_H_ +#include <memory> #include <string> #include <vector> -#include "base/memory/scoped_ptr.h" namespace chromecast { class CastSysInfo; -scoped_ptr<CastSysInfo> CreateSysInfo(); +std::unique_ptr<CastSysInfo> CreateSysInfo(); } // namespace chromecast diff --git a/chromium/chromecast/base/cast_sys_info_util_simple.cc b/chromium/chromecast/base/cast_sys_info_util_simple.cc index 68ab9dffb2c..0eb54a41aed 100644 --- a/chromium/chromecast/base/cast_sys_info_util_simple.cc +++ b/chromium/chromecast/base/cast_sys_info_util_simple.cc @@ -4,13 +4,14 @@ #include "chromecast/base/cast_sys_info_util.h" +#include "base/memory/ptr_util.h" #include "chromecast/base/cast_sys_info_dummy.h" namespace chromecast { // static -scoped_ptr<CastSysInfo> CreateSysInfo() { - return make_scoped_ptr(new CastSysInfoDummy()); +std::unique_ptr<CastSysInfo> CreateSysInfo() { + return base::WrapUnique(new CastSysInfoDummy()); } } // namespace chromecast diff --git a/chromium/chromecast/base/chromecast_switches.cc b/chromium/chromecast/base/chromecast_switches.cc index 25438ac9991..432e76321b6 100644 --- a/chromium/chromecast/base/chromecast_switches.cc +++ b/chromium/chromecast/base/chromecast_switches.cc @@ -4,8 +4,16 @@ #include "chromecast/base/chromecast_switches.h" +#include "base/command_line.h" + namespace switches { +// Value indicating whether flag from command line switch is true. +const char kSwitchValueTrue[] = "true"; + +// Value indicating whether flag from command line switch is false. +const char kSwitchValueFalse[] = "false"; + // Enable the CMA media pipeline. const char kEnableCmaMediaPipeline[] = "enable-cma-media-pipeline"; @@ -32,6 +40,11 @@ const char kLastLaunchedApp[] = "last-launched-app"; // started. const char kPreviousApp[] = "previous-app"; +// Flag indicating that a resource provider must be set up to provide cast +// receiver with resources. Apps cannot start until provided resources. +// This flag implies --alsa-check-close-timeout=0. +const char kAcceptResourceProvider[] = "accept-resource-provider"; + // Size of the ALSA output buffer in frames. This directly sets the latency of // the output device. Latency can be calculated by multiplying the sample rate // by the output buffer size. @@ -48,7 +61,39 @@ const char kAlsaOutputStartThreshold[] = "alsa-output-start-threshold"; const char kAlsaOutputAvailMin[] = "alsa-output-avail-min"; // Time in ms to wait before closing the PCM handle when no more mixer inputs -// remain. +// remain. Assumed to be 0 if --accept-resource-provider is present. const char kAlsaCheckCloseTimeout[] = "alsa-check-close-timeout"; +// Number of channels on the alsa output device that the stream mixer uses. +// Default is 2 channels. +const char kAlsaNumOutputChannels[] = "alsa-num-output-channels"; + +// Optional flag to set a fixed sample rate for the alsa device. +const char kAlsaFixedOutputSampleRate[] = "alsa-fixed-output-sample-rate"; + } // namespace switches + +namespace chromecast { + +bool GetSwitchValueBoolean(const std::string& switch_string, + const bool default_value) { + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switch_string)) { + if (command_line->GetSwitchValueASCII(switch_string) != + switches::kSwitchValueTrue && + command_line->GetSwitchValueASCII(switch_string) != + switches::kSwitchValueFalse && + command_line->GetSwitchValueASCII(switch_string) != "") { + LOG(WARNING) << "Invalid switch value " << switch_string << "=" + << command_line->GetSwitchValueASCII(switch_string) + << "; assuming default value of " << default_value; + return default_value; + } + return command_line->GetSwitchValueASCII(switch_string) != + switches::kSwitchValueFalse; + } + return default_value; +} + +} // namespace chromecast diff --git a/chromium/chromecast/base/chromecast_switches.h b/chromium/chromecast/base/chromecast_switches.h index 1ac84d878bc..4d30f995aa3 100644 --- a/chromium/chromecast/base/chromecast_switches.h +++ b/chromium/chromecast/base/chromecast_switches.h @@ -5,10 +5,16 @@ #ifndef CHROMECAST_BASE_CHROMECAST_SWITCHES_H_ #define CHROMECAST_BASE_CHROMECAST_SWITCHES_H_ +#include <string> + #include "build/build_config.h" namespace switches { +// Switch values +extern const char kSwitchValueTrue[]; +extern const char kSwitchValueFalse[]; + // Media switches extern const char kEnableCmaMediaPipeline[]; extern const char kHdmiSinkSupportedCodecs[]; @@ -29,13 +35,30 @@ extern const char kAllowHiddenMediaPlayback[]; extern const char kLastLaunchedApp[]; extern const char kPreviousApp[]; +// Cast Receiver switches +extern const char kAcceptResourceProvider[]; + // ALSA-based CMA switches. (Only valid for audio products.) extern const char kAlsaOutputBufferSize[]; extern const char kAlsaOutputPeriodSize[]; extern const char kAlsaOutputStartThreshold[]; extern const char kAlsaOutputAvailMin[]; extern const char kAlsaCheckCloseTimeout[]; +extern const char kAlsaNumOutputChannels[]; +extern const char kAlsaFixedOutputSampleRate[]; } // namespace switches +namespace chromecast { + +// Gets boolean value from switch |switch_string|. +// --|switch_string| -> true +// --|switch_string|="true" -> true +// --|switch_string|="false" -> false +// no switch named |switch_string| -> |default_value| +bool GetSwitchValueBoolean(const std::string& switch_string, + const bool default_value); + +} // namespace chromecast + #endif // CHROMECAST_BASE_CHROMECAST_SWITCHES_H_ diff --git a/chromium/chromecast/base/chromecast_switches_unittest.cc b/chromium/chromecast/base/chromecast_switches_unittest.cc new file mode 100644 index 00000000000..465456e1704 --- /dev/null +++ b/chromium/chromecast/base/chromecast_switches_unittest.cc @@ -0,0 +1,61 @@ +// 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 "base/command_line.h" +#include "chromecast/base/chromecast_switches.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromecast { + +TEST(ChromecastSwitchesTest, NoSwitch) { + if (base::CommandLine::CommandLine::InitializedForCurrentProcess()) + base::CommandLine::Reset(); + base::CommandLine::Init(0, nullptr); + EXPECT_TRUE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, true)); + EXPECT_FALSE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, false)); +} + +TEST(ChromecastSwitchesTest, NoSwitchValue) { + if (base::CommandLine::CommandLine::InitializedForCurrentProcess()) + base::CommandLine::Reset(); + base::CommandLine::Init(0, nullptr); + base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); + cl->AppendSwitch(switches::kEnableCmaMediaPipeline); + EXPECT_TRUE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, true)); + EXPECT_TRUE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, false)); +} + +TEST(ChromecastSwitchesTest, SwitchValueTrue) { + if (base::CommandLine::CommandLine::InitializedForCurrentProcess()) + base::CommandLine::Reset(); + base::CommandLine::Init(0, nullptr); + base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); + cl->AppendSwitchASCII(switches::kEnableCmaMediaPipeline, + switches::kSwitchValueTrue); + EXPECT_TRUE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, true)); + EXPECT_TRUE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, false)); +} + +TEST(ChromecastSwitchesTest, SwitchValueFalse) { + if (base::CommandLine::CommandLine::InitializedForCurrentProcess()) + base::CommandLine::Reset(); + base::CommandLine::Init(0, nullptr); + base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); + cl->AppendSwitchASCII(switches::kEnableCmaMediaPipeline, + switches::kSwitchValueFalse); + EXPECT_FALSE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, true)); + EXPECT_FALSE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, false)); +} + +TEST(ChromecastSwitchesTest, SwitchValueNonsense) { + if (base::CommandLine::CommandLine::InitializedForCurrentProcess()) + base::CommandLine::Reset(); + base::CommandLine::Init(0, nullptr); + base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); + cl->AppendSwitchASCII(switches::kEnableCmaMediaPipeline, "silverware"); + EXPECT_TRUE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, true)); + EXPECT_FALSE(GetSwitchValueBoolean(switches::kEnableCmaMediaPipeline, false)); +} + +} // namespace chromecast diff --git a/chromium/chromecast/base/component/BUILD.gn b/chromium/chromecast/base/component/BUILD.gn new file mode 100644 index 00000000000..82689625bfc --- /dev/null +++ b/chromium/chromecast/base/component/BUILD.gn @@ -0,0 +1,33 @@ +# 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. + +import("//chromecast/chromecast.gni") +import("//testing/test.gni") + +# GYP target: chromecast.gyp:cast_component +source_set("component") { + sources = [ + "component.cc", + "component.h", + "component_internal.h", + ] + + deps = [ + "//base", + ] +} + +# GYP target: chromecast_tests.gypi:cast_component_unittests +test("cast_component_unittests") { + sources = [ + "component_unittest.cc", + ] + + deps = [ + ":component", + "//base", + "//base/test:run_all_unittests", + "//testing/gtest", + ] +} diff --git a/chromium/chromecast/base/component/component.cc b/chromium/chromecast/base/component/component.cc new file mode 100644 index 00000000000..db203f9664a --- /dev/null +++ b/chromium/chromecast/base/component/component.cc @@ -0,0 +1,425 @@ +// 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 "chromecast/base/component/component.h" + +#include <set> + +#include "base/atomicops.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback_helpers.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" + +namespace chromecast { + +namespace { + +const base::subtle::AtomicWord kEnabledBit = 0x40000000; + +} // namespace + +namespace subtle { + +class DependencyCount : public base::RefCountedThreadSafe<DependencyCount> { + public: + explicit DependencyCount(ComponentBase* component) + : component_(component), + task_runner_(base::ThreadTaskRunnerHandle::Get()), + dep_count_(0), + disabling_(false) { + DCHECK(component_); + } + + void Detach() { + DCHECK(task_runner_->BelongsToCurrentThread()); + component_ = nullptr; + } + + void Disable() { + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(!disabling_); + disabling_ = true; + + std::set<DependencyBase*> dependents(strong_dependents_); + for (DependencyBase* dependent : dependents) + dependent->Disable(); + + while (true) { + AtomicWord deps = base::subtle::NoBarrier_Load(&dep_count_); + AtomicWord old_deps = base::subtle::Acquire_CompareAndSwap( + &dep_count_, deps, deps & ~kEnabledBit); + if (old_deps == deps) { + if ((deps & ~kEnabledBit) == 0) + DisableComplete(); + return; + } + } + } + + void Enable() { + DCHECK(task_runner_->BelongsToCurrentThread()); + disabling_ = false; + while (true) { + AtomicWord deps = base::subtle::NoBarrier_Load(&dep_count_); + DCHECK(!(deps & kEnabledBit)); + AtomicWord old_deps = base::subtle::Release_CompareAndSwap( + &dep_count_, deps, deps | kEnabledBit); + if (old_deps == deps) + break; + } + + for (DependencyBase* dependent : strong_dependents_) + dependent->Ready(component_); + } + + ComponentBase* WeakAcquireDep() { + while (true) { + AtomicWord deps = base::subtle::NoBarrier_Load(&dep_count_); + if (!(deps & kEnabledBit)) + return nullptr; + AtomicWord old_deps = + base::subtle::Acquire_CompareAndSwap(&dep_count_, deps, deps + 1); + // We depend on the fact that a component must be disabled (meaning that + // we will never reach this point) before it is destroyed. Therefore if + // we do reach this point, it is safe to return the raw pointer. + if (old_deps == deps) + return component_; + } + } + + void StrongAcquireDep(DependencyBase* dependent) { + DCHECK(dependent); + DCHECK(task_runner_->BelongsToCurrentThread()); + if (!component_) { + dependent->Disable(); + return; + } + + strong_dependents_.insert(dependent); + AtomicWord count = base::subtle::NoBarrier_AtomicIncrement(&dep_count_, 1); + DCHECK_GT(count, 0); + + if (count & kEnabledBit) { + dependent->Ready(component_); + } else { + component_->Enable(); + } + } + + void StrongReleaseDep(DependencyBase* dependent) { + DCHECK(dependent); + DCHECK(task_runner_->BelongsToCurrentThread()); + strong_dependents_.erase(dependent); + ReleaseDep(); + } + + void ReleaseDep() { + AtomicWord after = base::subtle::Barrier_AtomicIncrement(&dep_count_, -1); + DCHECK_GE(after, 0); + if (after == 0) + DisableComplete(); + } + + bool DependsOn(ComponentBase* component) { + DCHECK(task_runner_->BelongsToCurrentThread()); + if (!component_) + return false; + if (component_ == component) + return true; + return component_->DependsOn(component); + } + + private: + friend class base::RefCountedThreadSafe<DependencyCount>; + using AtomicWord = base::subtle::AtomicWord; + + ~DependencyCount() {} + + void DisableComplete() { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, base::Bind(&DependencyCount::DisableComplete, this)); + return; + } + // Need to make sure that Enable() was not called in the meantime. + if (base::subtle::NoBarrier_Load(&dep_count_) != 0 || !disabling_) + return; + // Ensure that we don't call DisableComplete() more than once per Disable(). + disabling_ = false; + DCHECK(component_); + DCHECK(strong_dependents_.empty()); + component_->DependencyCountDisableComplete(); + } + + ComponentBase* component_; + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + AtomicWord dep_count_; + bool disabling_; + std::set<DependencyBase*> strong_dependents_; + + DISALLOW_COPY_AND_ASSIGN(DependencyCount); +}; + +DependencyBase::DependencyBase(const WeakReferenceBase& dependency, + ComponentBase* dependent) + : dependent_(dependent), + dependency_(nullptr), + counter_(dependency.counter_) { + DCHECK(dependent_); + dependent_->AddDependency(this); +} + +DependencyBase::~DependencyBase() {} + +void DependencyBase::StartUsing() { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!dependency_); + counter_->StrongAcquireDep(this); +} + +void DependencyBase::StopUsing() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!dependency_) + return; + dependency_ = nullptr; + counter_->StrongReleaseDep(this); +} + +void DependencyBase::Ready(ComponentBase* dependency) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!dependency_); + DCHECK(dependency); + dependency_ = dependency; + dependent_->DependencyReady(); +} + +void DependencyBase::Disable() { + DCHECK(thread_checker_.CalledOnValidThread()); + dependent_->Disable(); +} + +bool DependencyBase::DependsOn(ComponentBase* component) { + return counter_->DependsOn(component); +} + +WeakReferenceBase::WeakReferenceBase(const ComponentBase& dependency) + : counter_(dependency.counter_) { + DCHECK(counter_); +} + +WeakReferenceBase::WeakReferenceBase(const DependencyBase& dependency) + : counter_(dependency.counter_) { + DCHECK(counter_); +} + +WeakReferenceBase::WeakReferenceBase(const WeakReferenceBase& other) + : counter_(other.counter_) { + DCHECK(counter_); +} + +WeakReferenceBase::WeakReferenceBase(WeakReferenceBase&& other) + : counter_(std::move(other.counter_)) { + DCHECK(counter_); +} + +WeakReferenceBase::~WeakReferenceBase() {} + +ScopedReferenceBase::ScopedReferenceBase( + const scoped_refptr<DependencyCount>& counter) + : counter_(counter) { + DCHECK(counter_); + dependency_ = counter_->WeakAcquireDep(); +} + +ScopedReferenceBase::ScopedReferenceBase(ScopedReferenceBase&& other) + : counter_(std::move(other.counter_)), dependency_(other.dependency_) { + DCHECK(counter_); + other.dependency_ = nullptr; +} + +ScopedReferenceBase::~ScopedReferenceBase() { + if (dependency_) + counter_->ReleaseDep(); +} + +} // namespace subtle + +ComponentBase::ComponentBase() + : task_runner_(base::ThreadTaskRunnerHandle::Get()), + state_(kStateDisabled), + async_call_in_progress_(false), + pending_dependency_count_(0), + observers_(new base::ObserverListThreadSafe<Observer>()) { + counter_ = new subtle::DependencyCount(this); +} + +ComponentBase::~ComponentBase() { + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK_EQ(kStateDisabled, state_) << "Components must be disabled " + << "before being destroyed"; + counter_->Detach(); +} + +void ComponentBase::Enable() { + DCHECK(task_runner_->BelongsToCurrentThread()); + if (state_ == kStateEnabling || state_ == kStateEnabled || + state_ == kStateDestroying) { + return; + } + state_ = kStateEnabling; + + if (strong_dependencies_.empty()) { + TryOnEnable(); + } else { + // Enable all strong dependencies first. + pending_dependency_count_ = strong_dependencies_.size(); + for (subtle::DependencyBase* dependency : strong_dependencies_) + dependency->StartUsing(); + } +} + +void ComponentBase::DependencyReady() { + DCHECK(task_runner_->BelongsToCurrentThread()); + if (state_ != kStateEnabling) + return; + DCHECK_GT(pending_dependency_count_, 0); + --pending_dependency_count_; + if (pending_dependency_count_ == 0) + TryOnEnable(); +} + +void ComponentBase::TryOnEnable() { + DCHECK_EQ(kStateEnabling, state_); + if (async_call_in_progress_) + return; + async_call_in_progress_ = true; + OnEnable(); +} + +void ComponentBase::OnEnableComplete(bool success) { + // Always post a task, to prevent the stack from getting too deep. + task_runner_->PostTask(FROM_HERE, + base::Bind(&ComponentBase::OnEnableCompleteInternal, + base::Unretained(this), success)); +} + +void ComponentBase::OnEnableCompleteInternal(bool success) { + async_call_in_progress_ = false; + DCHECK(state_ == kStateEnabling || state_ == kStateDisabling || + state_ == kStateDestroying); + if (state_ != kStateEnabling) { + if (success) { + TryOnDisable(); + } else { + OnDisableCompleteInternal(); + } + return; + } + + if (success) { + state_ = kStateEnabled; + counter_->Enable(); + } else { + Disable(); + } + observers_->Notify(FROM_HERE, &Observer::OnComponentEnabled, this, success); +} + +void ComponentBase::Destroy() { + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK_NE(kStateDestroying, state_); + if (state_ == kStateDisabled) { + delete this; + } else { + bool should_disable = (state_ != kStateDisabling); + state_ = kStateDestroying; + if (should_disable) + counter_->Disable(); + } +} + +void ComponentBase::AddObserver(Observer* observer) { + DCHECK(observer); + observers_->AddObserver(observer); +} + +void ComponentBase::RemoveObserver(Observer* observer) { + observers_->RemoveObserver(observer); +} + +void ComponentBase::Disable() { + DCHECK(task_runner_->BelongsToCurrentThread()); + if (state_ == kStateDisabling || state_ == kStateDisabled || + state_ == kStateDestroying) { + return; + } + state_ = kStateDisabling; + counter_->Disable(); +} + +void ComponentBase::DependencyCountDisableComplete() { + DCHECK(task_runner_->BelongsToCurrentThread()); + if (state_ == kStateDisabling || state_ == kStateDestroying) + TryOnDisable(); +} + +void ComponentBase::TryOnDisable() { + DCHECK(state_ == kStateDisabling || state_ == kStateDestroying); + if (async_call_in_progress_) + return; + async_call_in_progress_ = true; + OnDisable(); +} + +void ComponentBase::OnDisableComplete() { + // Always post a task, to prevent calls to Disable() from within Enable(). + task_runner_->PostTask(FROM_HERE, + base::Bind(&ComponentBase::OnDisableCompleteInternal, + base::Unretained(this))); +} + +void ComponentBase::OnDisableCompleteInternal() { + async_call_in_progress_ = false; + DCHECK(state_ == kStateEnabling || state_ == kStateDisabling || + state_ == kStateDestroying); + if (state_ == kStateEnabling) { + TryOnEnable(); + return; + } + + if (state_ == kStateDestroying) { + StopUsingDependencies(); + observers_->Notify(FROM_HERE, &Observer::OnComponentDisabled, this); + state_ = kStateDisabled; + delete this; + } else { + state_ = kStateDisabled; + StopUsingDependencies(); + observers_->Notify(FROM_HERE, &Observer::OnComponentDisabled, this); + } +} + +void ComponentBase::AddDependency(subtle::DependencyBase* dependency) { + DCHECK_EQ(kStateDisabled, state_); + DCHECK(!dependency->DependsOn(this)) << "Circular dependency detected"; + strong_dependencies_.push_back(dependency); +} + +void ComponentBase::StopUsingDependencies() { + for (subtle::DependencyBase* dependency : strong_dependencies_) + dependency->StopUsing(); +} + +bool ComponentBase::DependsOn(ComponentBase* component) { + for (subtle::DependencyBase* dependency : strong_dependencies_) { + if (dependency->DependsOn(component)) + return true; + } + return false; +} + +} // namespace chromecast diff --git a/chromium/chromecast/base/component/component.h b/chromium/chromecast/base/component/component.h new file mode 100644 index 00000000000..a545ea435d5 --- /dev/null +++ b/chromium/chromecast/base/component/component.h @@ -0,0 +1,327 @@ +// 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. + +// A component is a large, long-lived set of functionality that may be enabled +// or disabled at runtime. Some examples include: the multizone features, +// MetricsRecorder, or OpencastController. Components may depend on each other +// (ie, a component may call the public methods of other components); the +// Component infrastructure ensures that when a component is disabled, nothing +// that depends on it will call any of its methods until it is enabled again. +// +// Components may be used without a dependency relationship via a weak +// reference. A weak reference does not allow direct access to the component; +// instead, it must be either used to create a strict dependency (see below), or +// be converted to a scoped reference via Try(). Scoped references must be +// checked for validity before use (they are convertible to bool); an invalid +// scoped reference must not be used. Scoped references should be short-lived; +// to encourage this, they are only move-constructible and cannot be copied or +// assigned. +// +// If component Y depends on Component X, then Y has a Dependency reference +// to X. This causes Y to be disabled as X is being disabled (before X's +// OnDisable() method is called). Similarly, this dependency will cause X to be +// enabled when Y is being enabled (X will be enabled before Y's OnEnable() +// method is called). A component may freely access any of its dependencies +// as long as it is enabled. When a component is disabled, it must ensure that +// none of its dependencies will be used again until it is enabled. It is +// recommended to set up dependencies in your component's constructor; it is an +// error to add a dependency to a component that is not disabled. +// +// When a component is disabled, it will first recursively disable any other +// components that depend on it. It will also disable the creation of +// new scoped references. It then waits for all scoped references to be +// destroyed before calling OnDisable() to actually disable the component. +// +// Components MUST be disabled before they are deleted. For ease of use, a +// Destroy() method is provided. When Destroy() is called, it prevents the +// component from being enabled ever again, and then disables it, deleting it +// once it is disabled. +// +// Example usage: +// +// class MetricsRecorder : public Component<MetricsRecorder> { +// public: +// virtual ~MetricsRecorder() {} +// virtual void RecordEvent(const std::string& event) = 0; +// }; +// +// class SetupManager : public Component<SetupManager> { +// public: +// virtual ~SetupManager() {} +// virtual int GetMultizoneDelay() = 0; +// }; +// +// class Multizone : public Component<Multizone> { +// public: +// virtual ~Multizone() {} +// virtual void DoMultizoneStuff() = 0; +// }; +// +// class MetricsRecorderImpl : public MetricsRecorder { +// public: +// void OnEnable() override { +// // ... Enable metrics reporting ... +// OnEnableComplete(true); +// } +// +// // Release all resources; public methods will not be called after this. +// void OnDisable() override { +// OnDisableComplete(); +// } +// +// void RecordEvent(const std::string& event) override { +// // ... Record an event ... +// } +// }; +// +// class SetupManagerImpl : public SetupManager { +// public: +// void OnEnable() override { +// // ... Enable setup manager ... +// // OnEnableComplete() may be called asynchronously. +// base::ThreadTaskRunnerHandle::Get()->PostTask( +// FROM_HERE, base::Bind(&SetupManagerImpl::CompleteEnable, +// base::Unretained(this))); +// } +// +// void CompleteEnable() { +// OnEnableComplete(true); +// } +// +// void OnDisable() override { +// OnDisableComplete(); +// } +// +// int GetMultizoneDelay() override { return 0; } +// }; +// +// class MultizoneImpl : public Multizone { +// public: +// MultizoneImpl(const MetricsRecorder::WeakRef& metrics_recorder, +// const SetupManager::WeakRef& setup_manager) +// : metrics_recorder_(metrics_recorder, this), +// setup_manager_(setup_manager) { +// // We can try to use weak deps even before this component is enabled. +// // However, we MUST NOT attempt to use any strong dependencies. +// if (auto setup = setup_manager_.Try()) { +// int delay = setup->GetMultizoneDelay(); +// // ... Do something with delay ... +// } +// } +// +// void OnEnable() override { +// // ... Enable multizone ... +// // Can use strong dependencies directly +// metrics_recorder_->RecordEvent("enable multizone"); +// OnEnableComplete(); +// } +// +// void OnDisable() override { +// // Can still use strong dependencies here. However, this method MUST +// // ensure that strong dependencies will NOT be used after it returns. +// metrics_recorder_->RecordEvent("disable multizone"); +// OnDisableComplete(); +// } +// +// void DoMultizoneStuff() { +// metrics_recorder_->RecordEvent("multizone stuff"); +// // You have to Try() every time you use a weak dependency. +// if (auto setup = setup_manager_.Try()) { +// int delay = setup->GetMultizoneDelay(); +// // ... Do something with delay ... +// } +// } +// +// private: +// MetricsRecorder::Dependency metrics_recorder_; +// SetupManager::WeakRef setup_manager_; +// }; + +#ifndef CHROMECAST_BASE_COMPONENT_COMPONENT_H_ +#define CHROMECAST_BASE_COMPONENT_COMPONENT_H_ + +#include <vector> + +#include "base/callback.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list_threadsafe.h" +#include "base/threading/thread_checker.h" +#include "chromecast/base/component/component_internal.h" + +namespace base { +class SingleThreadTaskRunner; +} // namespace base + +namespace chromecast { + +class ComponentBase { + public: + class Observer { + public: + // Called when a component finishes being enabled. If the component was + // enabled successfully, |success| will be |true|. Note that access to + // |component| is not guaranteed to be safe; since the observers are + // notified asynchronously, |component| may have been already deleted. + virtual void OnComponentEnabled(ComponentBase* component, bool success) {} + // Called when a component has been disabled. Access to |component| is not + // guaranteed to be safe. + virtual void OnComponentDisabled(ComponentBase* component) {} + + protected: + virtual ~Observer() {} + }; + + virtual ~ComponentBase(); + + // Enables this component if possible. Attempts to enable all strong + // dependencies first. It is OK to call Disable() while the component is in + // the process of being enabled. All components MUST be created/enabled/ + // disabled/destroyed on the same thread. + // Note that enabling a component may occur asynchronously; components must + // always be accessed through a Dependency or WeakReference to ensure safety. + // TODO(kmackay) Consider allowing components to be used on any thread. + void Enable(); + + // Disables this component; disabling may complete asynchronously. It is OK to + // call Enable() again while the component is being disabled. Note that a + // component MUST be disabled (or never enabled) before it is deleted. + void Disable(); + + // Deletes this component, disabling it first if necessary. + void Destroy(); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + protected: + ComponentBase(); + + // Enables the component implementation. This method must set things up so + // that any public method calls are valid, and then call OnEnableComplete(), + // passing in |true| if the enable was successful, |false| otherwise. + // OnEnableComplete() may be called from any thread. OnEnable() will not be + // called again until after the component has been disabled, and will not be + // called during an ongoing OnDisable() call (so if OnDisable() is called, + // then OnEnable() will not be called until OnDisableComplete() has been + // called). This method is called only on the thread that the component was + // created on. + virtual void OnEnable() = 0; + + // Disables the component implementation. This is not called until there are + // no more live dependencies, so there will be no more public method calls + // to the component until after OnEnable() is called again. This method must + // do whatever is necessary to ensure that no more calls to dependencies of + // this component will be made, and then call the |disabled_cb|. The + // |disabled_cb| may be called from any thread. This method is called only on + // the thread that the component was created on. + virtual void OnDisable() = 0; + + // Handles the success/failure of a call to OnEnable(). When OnEnable() is + // called, it must eventually call OnEnableComplete() (after the component is + // ready to be used by dependents), passing in |true| if the component was + // enabled successfully. If |success| is false, then OnDisable() will be + // called immediately to return the component to a consistent disabled state. + // May be called on any thread. + void OnEnableComplete(bool success); + + // Handles the completion of a call to OnDisable(). When OnDisable() is + // called, it must eventually call OnDisableComplete() (after ensuring that + // none of the component's strong dependencies will be used anymore). May be + // called on any thread. + void OnDisableComplete(); + + private: + friend class subtle::DependencyCount; + friend class subtle::DependencyBase; + friend class subtle::WeakReferenceBase; + + enum State { + kStateDisabled, + kStateDisabling, + kStateEnabled, + kStateEnabling, + kStateDestroying + }; + + void DependencyReady(); + void TryOnEnable(); + void OnEnableCompleteInternal(bool success); + void DependencyCountDisableComplete(); + void TryOnDisable(); + void OnDisableCompleteInternal(); + void AddDependency(subtle::DependencyBase* dependency); + void StopUsingDependencies(); + // Returns |true| if |component| is a transitive dependency of this component. + bool DependsOn(ComponentBase* component); + + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<subtle::DependencyCount> counter_; + std::vector<subtle::DependencyBase*> strong_dependencies_; + State state_; + // |true| when a call to OnEnable()/OnDisable() is in progress. + bool async_call_in_progress_; + int pending_dependency_count_; + const scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_; + + DISALLOW_COPY_AND_ASSIGN(ComponentBase); +}; + +template <typename C> +class StrongDependency : public subtle::DependencyBase { + public: + StrongDependency(const WeakReference<C>& dependency, ComponentBase* dependent) + : subtle::DependencyBase(dependency, dependent) {} + + C* operator->() const { + DCHECK(dependency_); + return static_cast<C*>(dependency_); + } + + private: + DISALLOW_COPY_AND_ASSIGN(StrongDependency); +}; + +template <typename C> +class WeakReference : public subtle::WeakReferenceBase { + public: + explicit WeakReference(const C& dependency) : WeakReferenceBase(dependency) {} + explicit WeakReference(const StrongDependency<C>& dependency) + : subtle::WeakReferenceBase(dependency) {} + + // Explicitly allow copy. + WeakReference(const WeakReference& other) = default; + WeakReference(WeakReference&& other) = default; + + // Disallow assignment. + void operator=(const WeakReference&) = delete; + + // Try to get a scoped reference. Expected usage: + // if (auto ref = weak.Try()) { + // // ... use ref ... + // } + subtle::Ref_DO_NOT_DECLARE<C> Try() const { + return subtle::Ref_DO_NOT_DECLARE<C>(counter_); + } +}; + +template <typename C> +class Component : public ComponentBase { + public: + using WeakRef = WeakReference<C>; + using Dependency = StrongDependency<C>; + + Component() = default; + + WeakRef GetRef() { return WeakRef(*static_cast<C*>(this)); } + + private: + DISALLOW_COPY_AND_ASSIGN(Component); +}; + +} // namespace chromecast + +#endif // CHROMECAST_BASE_COMPONENT_COMPONENT_H_ diff --git a/chromium/chromecast/base/component/component_internal.h b/chromium/chromecast/base/component/component_internal.h new file mode 100644 index 00000000000..85a6757ecd2 --- /dev/null +++ b/chromium/chromecast/base/component/component_internal.h @@ -0,0 +1,121 @@ +// 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. + +#ifndef CHROMECAST_BASE_COMPONENT_COMPONENT_INTERNAL_H_ +#define CHROMECAST_BASE_COMPONENT_COMPONENT_INTERNAL_H_ + +#include <set> +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list_threadsafe.h" +#include "base/threading/thread_checker.h" + +namespace chromecast { + +template <typename C> +class WeakReference; + +class ComponentBase; + +namespace subtle { + +class WeakReferenceBase; + +// Manages thread-safe dependency counting. Instances of this class are +// RefCountedThreadSafe since they must live as long as any dependent. +class DependencyCount; + +// Base class for strong dependencies. A strong dependency is tied to a +// specific dependent component instance. This allows dependents to be +// disabled before the component they depend on. May be used on any thread. +class DependencyBase { + public: + DependencyBase(const WeakReferenceBase& dependency, ComponentBase* dependent); + ~DependencyBase(); + + void StartUsing(); + void StopUsing(); + bool DependsOn(ComponentBase* component); + + protected: + ComponentBase* const dependent_; + ComponentBase* dependency_; + + private: + friend class DependencyCount; + friend class WeakReferenceBase; + + void Ready(ComponentBase* dependency); + void Disable(); + + const scoped_refptr<DependencyCount> counter_; + base::ThreadChecker thread_checker_; + + DISALLOW_COPY_AND_ASSIGN(DependencyBase); +}; + +// Base class for weak dependencies. Weak dependencies cannot be used +// directly; they must be converted to a strong dependency or a temp +// dependency first. May be converted on any thread. +class WeakReferenceBase { + protected: + friend class DependencyBase; + + explicit WeakReferenceBase(const ComponentBase& dependency); + explicit WeakReferenceBase(const DependencyBase& dependency); + WeakReferenceBase(const WeakReferenceBase& other); + WeakReferenceBase(WeakReferenceBase&& other); + ~WeakReferenceBase(); + + const scoped_refptr<DependencyCount> counter_; +}; + +// Base class for temp dependencies. Temp dependencies are meant for +// short-term use only, but can be used from any thread. +class ScopedReferenceBase { + protected: + explicit ScopedReferenceBase(const scoped_refptr<DependencyCount>& counter); + ScopedReferenceBase(ScopedReferenceBase&& other); + ~ScopedReferenceBase(); + + const scoped_refptr<DependencyCount> counter_; + ComponentBase* dependency_; +}; + +// This class is not intended to be long-lived, and should not be declared as +// a variable type (eg, don't use it as a member variable). Instead, use auto +// (see WeakReference::Try() for an example). +template <typename C> +class Ref_DO_NOT_DECLARE : public ScopedReferenceBase { + public: + Ref_DO_NOT_DECLARE(Ref_DO_NOT_DECLARE&& other) = default; + + C* operator->() const { + DCHECK(dependency_); + return static_cast<C*>(dependency_); + } + + explicit operator bool() const { return (dependency_ != nullptr); } + + private: + friend class WeakReference<C>; + + explicit Ref_DO_NOT_DECLARE(const scoped_refptr<DependencyCount>& counter) + : ScopedReferenceBase(counter) {} + + Ref_DO_NOT_DECLARE(const Ref_DO_NOT_DECLARE& other) = delete; + Ref_DO_NOT_DECLARE& operator=(const Ref_DO_NOT_DECLARE& rhs) = delete; + Ref_DO_NOT_DECLARE& operator=(Ref_DO_NOT_DECLARE&& rhs) = delete; +}; + +} // namespace subtle +} // namespace chromecast + +#endif // CHROMECAST_BASE_COMPONENT_COMPONENT_INTERNAL_H_ diff --git a/chromium/chromecast/base/component/component_unittest.cc b/chromium/chromecast/base/component/component_unittest.cc new file mode 100644 index 00000000000..2c0fd2ed99e --- /dev/null +++ b/chromium/chromecast/base/component/component_unittest.cc @@ -0,0 +1,379 @@ +// 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 "chromecast/base/component/component.h" + +#include <memory> + +#include "base/location.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/thread_task_runner_handle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromecast { + +class ComponentTest : public ::testing::Test { + protected: + ComponentTest() : message_loop_(new base::MessageLoop()) {} + + const std::unique_ptr<base::MessageLoop> message_loop_; +}; + +using ComponentDeathTest = ComponentTest; + +class ComponentB; +class ComponentC; +class ComponentA : public Component<ComponentA> { + public: + void MakeSelfDependency() { + a_.reset(new Component<ComponentA>::Dependency(GetRef(), this)); + } + + void MakeCircularDependency(const Component<ComponentB>::WeakRef& b) { + b_.reset(new Component<ComponentB>::Dependency(b, this)); + } + + void MakeTransitiveCircularDependency( + const Component<ComponentC>::WeakRef& c) { + c_.reset(new Component<ComponentC>::Dependency(c, this)); + } + + void OnEnable() override { + if (!fail_enable_) { + enabled_ = true; + Test(); + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ComponentA::OnEnableComplete, + base::Unretained(this), !fail_enable_)); + } + + void OnDisable() override { + if (enabled_) + Test(); + enabled_ = false; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&ComponentA::OnDisableComplete, base::Unretained(this))); + } + + void Test() { + EXPECT_TRUE(enabled_); + EXPECT_FALSE(fail_enable_); + } + + bool enabled() const { return enabled_; } + void FailEnable() { fail_enable_ = true; } + + private: + bool enabled_ = false; + bool fail_enable_ = false; + + std::unique_ptr<Component<ComponentA>::Dependency> a_; + std::unique_ptr<Component<ComponentB>::Dependency> b_; + std::unique_ptr<Component<ComponentC>::Dependency> c_; +}; + +class ComponentB : public Component<ComponentB> { + public: + explicit ComponentB(const ComponentA::WeakRef& a) : a_(a, this) {} + + void OnEnable() override { + if (!fail_enable_) { + enabled_ = true; + Test(); + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ComponentB::OnEnableComplete, + base::Unretained(this), !fail_enable_)); + } + + void OnDisable() override { + if (enabled_) + Test(); + enabled_ = false; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&ComponentB::OnDisableComplete, base::Unretained(this))); + } + + void Test() { + EXPECT_TRUE(enabled_); + EXPECT_FALSE(fail_enable_); + a_->Test(); + } + + bool enabled() const { return enabled_; } + void FailEnable() { fail_enable_ = true; } + + private: + bool enabled_ = false; + bool fail_enable_ = false; + + ComponentA::Dependency a_; +}; + +class ComponentC : public Component<ComponentC> { + public: + explicit ComponentC(const ComponentB::WeakRef& b) : b_(b, this) {} + + void OnEnable() override { + if (!fail_enable_) { + enabled_ = true; + Test(); + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ComponentC::OnEnableComplete, + base::Unretained(this), !fail_enable_)); + } + + void OnDisable() override { + if (enabled_) + Test(); + enabled_ = false; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&ComponentC::OnDisableComplete, base::Unretained(this))); + } + + void Test() { + EXPECT_TRUE(enabled_); + EXPECT_FALSE(fail_enable_); + b_->Test(); + } + + bool enabled() const { return enabled_; } + void FailEnable() { fail_enable_ = true; } + + private: + bool enabled_ = false; + bool fail_enable_ = false; + + ComponentB::Dependency b_; +}; + +#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST +TEST_F(ComponentDeathTest, SelfDependency) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + ComponentA a; + EXPECT_DEATH(a.MakeSelfDependency(), "Circular dependency"); +} + +TEST_F(ComponentDeathTest, CircularDependency) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + ComponentA a; + ComponentB b(a.GetRef()); + EXPECT_DEATH(a.MakeCircularDependency(b.GetRef()), "Circular dependency"); +} + +TEST_F(ComponentDeathTest, TransitiveCircularDependency) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + ComponentA a; + ComponentB b(a.GetRef()); + ComponentC c(b.GetRef()); + EXPECT_DEATH(a.MakeTransitiveCircularDependency(c.GetRef()), + "Circular dependency"); +} +#endif // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && + // GTEST_HAS_DEATH_TEST + +TEST_F(ComponentTest, SimpleEnable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, TransitiveEnable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + std::unique_ptr<ComponentB> b(new ComponentB(a->GetRef())); + std::unique_ptr<ComponentC> c(new ComponentC(b->GetRef())); + c->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(a->enabled()); + EXPECT_TRUE(b->enabled()); + EXPECT_TRUE(c->enabled()); + a.release()->Destroy(); + b.release()->Destroy(); + c.release()->Destroy(); +} + +TEST_F(ComponentTest, FailEnable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->FailEnable(); + a->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, TransitiveFailEnable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + std::unique_ptr<ComponentB> b(new ComponentB(a->GetRef())); + std::unique_ptr<ComponentC> c(new ComponentC(b->GetRef())); + a->FailEnable(); + c->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + EXPECT_FALSE(b->enabled()); + EXPECT_FALSE(c->enabled()); + a.release()->Destroy(); + b.release()->Destroy(); + c.release()->Destroy(); +} + +TEST_F(ComponentTest, DisableWhileEnabling) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->Enable(); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, EnableTwice) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->Enable(); + a->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, DisableTwice) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(a->enabled()); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, DisableAfterFailedEnable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->FailEnable(); + a->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, DisableAfterNeverEnabled) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, DisableDependencyWhileEnabling) { + std::unique_ptr<ComponentA> a(new ComponentA()); + std::unique_ptr<ComponentB> b(new ComponentB(a->GetRef())); + std::unique_ptr<ComponentC> c(new ComponentC(b->GetRef())); + b->Enable(); + message_loop_->RunUntilIdle(); + c->Enable(); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + EXPECT_FALSE(b->enabled()); + EXPECT_FALSE(c->enabled()); + a.release()->Destroy(); + b.release()->Destroy(); + c.release()->Destroy(); +} + +TEST_F(ComponentTest, EnableDisableEnable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->Enable(); + a->Disable(); + a->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, DisableEnableDisable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + a->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(a->enabled()); + a->Disable(); + a->Enable(); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, TransitiveEnableDisableEnable) { + std::unique_ptr<ComponentA> a(new ComponentA()); + std::unique_ptr<ComponentB> b(new ComponentB(a->GetRef())); + std::unique_ptr<ComponentC> c(new ComponentC(b->GetRef())); + a->Enable(); + message_loop_->RunUntilIdle(); + c->Enable(); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + EXPECT_FALSE(b->enabled()); + EXPECT_FALSE(c->enabled()); + c->Enable(); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(a->enabled()); + EXPECT_TRUE(b->enabled()); + EXPECT_TRUE(c->enabled()); + a.release()->Destroy(); + b.release()->Destroy(); + c.release()->Destroy(); +} + +TEST_F(ComponentTest, WeakRefs) { + std::unique_ptr<ComponentA> a(new ComponentA()); + ComponentA::WeakRef weak = a->GetRef(); + EXPECT_FALSE(weak.Try()); + a->Enable(); + EXPECT_FALSE(weak.Try()); + message_loop_->RunUntilIdle(); + EXPECT_TRUE(weak.Try()); + weak.Try()->Test(); + a->Disable(); + message_loop_->RunUntilIdle(); + EXPECT_FALSE(weak.Try()); + a.release()->Destroy(); +} + +TEST_F(ComponentTest, WeakRefsKeepEnabled) { + std::unique_ptr<ComponentA> a(new ComponentA()); + ComponentA::WeakRef weak = a->GetRef(); + EXPECT_FALSE(weak.Try()); + a->Enable(); + EXPECT_FALSE(weak.Try()); + message_loop_->RunUntilIdle(); + { + auto held_ref = weak.Try(); + EXPECT_TRUE(held_ref); + held_ref->Test(); + a->Disable(); + message_loop_->RunUntilIdle(); + // The held ref keeps |a| enabled until it goes out of scope. + EXPECT_TRUE(a->enabled()); + } + message_loop_->RunUntilIdle(); + EXPECT_FALSE(a->enabled()); + EXPECT_FALSE(weak.Try()); + a.release()->Destroy(); +} + +} // namespace chromecast diff --git a/chromium/chromecast/base/device_capabilities.h b/chromium/chromecast/base/device_capabilities.h index 88d952569a3..bac412e774f 100644 --- a/chromium/chromecast/base/device_capabilities.h +++ b/chromium/chromecast/base/device_capabilities.h @@ -5,11 +5,11 @@ #ifndef CHROMECAST_BASE_DEVICE_CAPABILITIES_H_ #define CHROMECAST_BASE_DEVICE_CAPABILITIES_H_ +#include <memory> #include <string> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" namespace base { class DictionaryValue; @@ -75,7 +75,7 @@ class DeviceCapabilities { // to it must be handled serially. Returns response through // SetValidatedValue(). virtual void Validate(const std::string& path, - scoped_ptr<base::Value> proposed_value) = 0; + std::unique_ptr<base::Value> proposed_value) = 0; protected: explicit Validator(DeviceCapabilities* capabilities); @@ -88,7 +88,7 @@ class DeviceCapabilities { // DeviceCapabilities. This method passes these parameters to // DeviceCapabilities, where |path| is updated internally to |new_value|. void SetValidatedValue(const std::string& path, - scoped_ptr<base::Value> new_value) const; + std::unique_ptr<base::Value> new_value) const; private: DeviceCapabilities* const capabilities_; @@ -118,11 +118,11 @@ class DeviceCapabilities { // Constructs empty dictionary with no capabilities. Data(); // Uses |dictionary| as capabilities dictionary. - explicit Data(scoped_ptr<const base::DictionaryValue> dictionary); + explicit Data(std::unique_ptr<const base::DictionaryValue> dictionary); ~Data(); - const scoped_ptr<const base::DictionaryValue> dictionary_; - const scoped_ptr<const std::string> json_string_; + const std::unique_ptr<const base::DictionaryValue> dictionary_; + const std::unique_ptr<const std::string> json_string_; DISALLOW_COPY_AND_ASSIGN(Data); }; @@ -141,11 +141,11 @@ class DeviceCapabilities { // singleton, there is meant to be a single instance owned by another module. // The instance should be created early enough for all managers to register // themselves, and then live long enough for all managers to unregister. - static scoped_ptr<DeviceCapabilities> Create(); + static std::unique_ptr<DeviceCapabilities> Create(); // Creates an instance where all the default capabilities are initialized // to a predefined default value, and no Validators are registered. For use // only in unit tests. - static scoped_ptr<DeviceCapabilities> CreateForTesting(); + static std::unique_ptr<DeviceCapabilities> CreateForTesting(); // Registers a Validator for a capability. A given key must only be // registered once, and must be unregistered before calling Register() again. @@ -180,7 +180,7 @@ class DeviceCapabilities { // Returns a deep copy of the value at |path|. If the capability at |path| // does not exist, a null scoped_ptr is returned. - virtual scoped_ptr<base::Value> GetCapability( + virtual std::unique_ptr<base::Value> GetCapability( const std::string& path) const = 0; // Use this method to access dictionary and JSON string. No deep copying is @@ -199,7 +199,7 @@ class DeviceCapabilities { // method. Client code may use the Observer interface to determine the // ultimate value used. This method is asynchronous. virtual void SetCapability(const std::string& path, - scoped_ptr<base::Value> proposed_value) = 0; + std::unique_ptr<base::Value> proposed_value) = 0; // Iterates through entries in |dict_value| and calls SetCapability() for // each one. This method is asynchronous. virtual void MergeDictionary(const base::DictionaryValue& dict_value) = 0; @@ -217,12 +217,12 @@ class DeviceCapabilities { static scoped_refptr<Data> CreateData(); // Uses |dictionary| as capabilities dictionary. static scoped_refptr<Data> CreateData( - scoped_ptr<const base::DictionaryValue> dictionary); + std::unique_ptr<const base::DictionaryValue> dictionary); private: // Does actual internal update of |path| to |new_value|. virtual void SetValidatedValue(const std::string& path, - scoped_ptr<base::Value> new_value) = 0; + std::unique_ptr<base::Value> new_value) = 0; DISALLOW_COPY_AND_ASSIGN(DeviceCapabilities); }; diff --git a/chromium/chromecast/base/device_capabilities_impl.cc b/chromium/chromecast/base/device_capabilities_impl.cc index 6fb75bec2aa..c3dfea0d07e 100644 --- a/chromium/chromecast/base/device_capabilities_impl.cc +++ b/chromium/chromecast/base/device_capabilities_impl.cc @@ -5,9 +5,11 @@ #include "chromecast/base/device_capabilities_impl.h" #include <stddef.h> + #include <utility> #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/values.h" @@ -51,22 +53,22 @@ const char DeviceCapabilities::kKeyHiResAudioSupported[] = "hi_res_audio_supported"; // static -scoped_ptr<DeviceCapabilities> DeviceCapabilities::Create() { - return make_scoped_ptr(new DeviceCapabilitiesImpl); +std::unique_ptr<DeviceCapabilities> DeviceCapabilities::Create() { + return base::WrapUnique(new DeviceCapabilitiesImpl); } // static -scoped_ptr<DeviceCapabilities> DeviceCapabilities::CreateForTesting() { +std::unique_ptr<DeviceCapabilities> DeviceCapabilities::CreateForTesting() { DeviceCapabilities* capabilities = new DeviceCapabilitiesImpl; capabilities->SetCapability( kKeyBluetoothSupported, - make_scoped_ptr(new base::FundamentalValue(false))); + base::WrapUnique(new base::FundamentalValue(false))); capabilities->SetCapability( - kKeyDisplaySupported, make_scoped_ptr(new base::FundamentalValue(true))); + kKeyDisplaySupported, base::WrapUnique(new base::FundamentalValue(true))); capabilities->SetCapability( kKeyHiResAudioSupported, - make_scoped_ptr(new base::FundamentalValue(false))); - return make_scoped_ptr(capabilities); + base::WrapUnique(new base::FundamentalValue(false))); + return base::WrapUnique(capabilities); } scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData() { @@ -74,7 +76,7 @@ scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData() { } scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData( - scoped_ptr<const base::DictionaryValue> dictionary) { + std::unique_ptr<const base::DictionaryValue> dictionary) { DCHECK(dictionary.get()); return make_scoped_refptr(new Data(std::move(dictionary))); } @@ -86,7 +88,7 @@ DeviceCapabilities::Validator::Validator(DeviceCapabilities* capabilities) void DeviceCapabilities::Validator::SetValidatedValue( const std::string& path, - scoped_ptr<base::Value> new_value) const { + std::unique_ptr<base::Value> new_value) const { capabilities_->SetValidatedValue(path, std::move(new_value)); } @@ -97,7 +99,7 @@ DeviceCapabilities::Data::Data() } DeviceCapabilities::Data::Data( - scoped_ptr<const base::DictionaryValue> dictionary) + std::unique_ptr<const base::DictionaryValue> dictionary) : dictionary_(std::move(dictionary)), json_string_(SerializeToJson(*dictionary_)) { DCHECK(dictionary_.get()); @@ -120,7 +122,7 @@ DeviceCapabilitiesImpl::ValidatorInfo::~ValidatorInfo() { void DeviceCapabilitiesImpl::ValidatorInfo::Validate( const std::string& path, - scoped_ptr<base::Value> proposed_value) const { + std::unique_ptr<base::Value> proposed_value) const { // Check that we are running Validate on the same thread that ValidatorInfo // was constructed on. DCHECK(task_runner_->BelongsToCurrentThread()); @@ -148,7 +150,7 @@ void DeviceCapabilitiesImpl::Register(const std::string& key, base::AutoLock auto_lock(validation_lock_); bool added = - validator_map_.add(key, make_scoped_ptr(new ValidatorInfo(validator))) + validator_map_.add(key, base::WrapUnique(new ValidatorInfo(validator))) .second; // Check that a validator has not already been registered for this key DCHECK(added); @@ -205,12 +207,12 @@ bool DeviceCapabilitiesImpl::HiResAudioSupported() const { return hi_res_audio_supported; } -scoped_ptr<base::Value> DeviceCapabilitiesImpl::GetCapability( +std::unique_ptr<base::Value> DeviceCapabilitiesImpl::GetCapability( const std::string& path) const { scoped_refptr<Data> data_ref = GetData(); const base::Value* value = nullptr; bool found_path = data_ref->dictionary().Get(path, &value); - return found_path ? value->CreateDeepCopy() : scoped_ptr<base::Value>(); + return found_path ? value->CreateDeepCopy() : std::unique_ptr<base::Value>(); } scoped_refptr<DeviceCapabilities::Data> @@ -224,7 +226,7 @@ DeviceCapabilitiesImpl::GetData() const { void DeviceCapabilitiesImpl::SetCapability( const std::string& path, - scoped_ptr<base::Value> proposed_value) { + std::unique_ptr<base::Value> proposed_value) { DCHECK(proposed_value.get()); if (!IsValidPath(path)) { LOG(DFATAL) << "Invalid capability path encountered for SetCapability()"; @@ -276,7 +278,7 @@ void DeviceCapabilitiesImpl::RemoveCapabilitiesObserver(Observer* observer) { void DeviceCapabilitiesImpl::SetValidatedValue( const std::string& path, - scoped_ptr<base::Value> new_value) { + std::unique_ptr<base::Value> new_value) { // All internal writes/modifications of capabilities must occur on same // thread to avoid race conditions. if (!task_runner_for_writes_->BelongsToCurrentThread()) { @@ -305,7 +307,7 @@ void DeviceCapabilitiesImpl::SetValidatedValue( // data_lock_. If we were to lock and modify the capabilities // dictionary directly, there may be expensive writes that block other // threads. - scoped_ptr<base::DictionaryValue> dictionary_deep_copy( + std::unique_ptr<base::DictionaryValue> dictionary_deep_copy( data_->dictionary().CreateDeepCopy()); dictionary_deep_copy->Set(path, std::move(new_value)); scoped_refptr<Data> new_data(CreateData(std::move(dictionary_deep_copy))); diff --git a/chromium/chromecast/base/device_capabilities_impl.h b/chromium/chromecast/base/device_capabilities_impl.h index 07666208d63..70917a5acb3 100644 --- a/chromium/chromecast/base/device_capabilities_impl.h +++ b/chromium/chromecast/base/device_capabilities_impl.h @@ -5,6 +5,8 @@ #ifndef CHROMECAST_BASE_DEVICE_CAPABILITIES_IMPL_H_ #define CHROMECAST_BASE_DEVICE_CAPABILITIES_IMPL_H_ +#include <string> + #include "base/containers/scoped_ptr_hash_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -29,10 +31,11 @@ class DeviceCapabilitiesImpl : public DeviceCapabilities { bool BluetoothSupported() const override; bool DisplaySupported() const override; bool HiResAudioSupported() const override; - scoped_ptr<base::Value> GetCapability(const std::string& path) const override; + std::unique_ptr<base::Value> GetCapability( + const std::string& path) const override; scoped_refptr<Data> GetData() const override; void SetCapability(const std::string& path, - scoped_ptr<base::Value> proposed_value) override; + std::unique_ptr<base::Value> proposed_value) override; void MergeDictionary(const base::DictionaryValue& dict_value) override; void AddCapabilitiesObserver(Observer* observer) override; void RemoveCapabilitiesObserver(Observer* observer) override; @@ -50,7 +53,7 @@ class DeviceCapabilitiesImpl : public DeviceCapabilities { } void Validate(const std::string& path, - scoped_ptr<base::Value> proposed_value) const; + std::unique_ptr<base::Value> proposed_value) const; private: Validator* const validator_; @@ -67,14 +70,14 @@ class DeviceCapabilitiesImpl : public DeviceCapabilities { // Map from capability key to corresponding ValidatorInfo. Gets updated // in Register()/Unregister(). - typedef base::ScopedPtrHashMap<std::string, scoped_ptr<ValidatorInfo>> + typedef base::ScopedPtrHashMap<std::string, std::unique_ptr<ValidatorInfo>> ValidatorMap; // Internal constructor used by static DeviceCapabilities::Create*() methods. DeviceCapabilitiesImpl(); void SetValidatedValue(const std::string& path, - scoped_ptr<base::Value> new_value) override; + std::unique_ptr<base::Value> new_value) override; // Lock for reading/writing data_ pointer mutable base::Lock data_lock_; diff --git a/chromium/chromecast/base/device_capabilities_impl_unittest.cc b/chromium/chromecast/base/device_capabilities_impl_unittest.cc index c1889fc5d97..abfba30926a 100644 --- a/chromium/chromecast/base/device_capabilities_impl_unittest.cc +++ b/chromium/chromecast/base/device_capabilities_impl_unittest.cc @@ -8,6 +8,7 @@ #include <utility> #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/values.h" @@ -26,7 +27,7 @@ const char kSampleDictionaryCapability[] = "}"; void GetSampleDefaultCapability(std::string* key, - scoped_ptr<base::Value>* init_value); + std::unique_ptr<base::Value>* init_value); void TestBasicOperations(DeviceCapabilities* capabilities); // Simple capability manager that implements the Validator interface. Either @@ -39,7 +40,7 @@ class FakeCapabilityManagerSimple : public DeviceCapabilities::Validator { // untouched. FakeCapabilityManagerSimple(DeviceCapabilities* capabilities, const std::string& key, - scoped_ptr<base::Value> init_value, + std::unique_ptr<base::Value> init_value, bool accept_changes) : DeviceCapabilities::Validator(capabilities), key_(key), @@ -55,8 +56,8 @@ class FakeCapabilityManagerSimple : public DeviceCapabilities::Validator { } void Validate(const std::string& path, - scoped_ptr<base::Value> proposed_value) override { - ASSERT_TRUE(path.find(key_) == 0); + std::unique_ptr<base::Value> proposed_value) override { + ASSERT_EQ(path.find(key_), 0ul); if (accept_changes_) SetValidatedValue(path, std::move(proposed_value)); } @@ -83,7 +84,7 @@ class FakeCapabilityManagerComplex : public DeviceCapabilities::Validator { // Runs TestBasicOperations(). void Validate(const std::string& path, - scoped_ptr<base::Value> proposed_value) override { + std::unique_ptr<base::Value> proposed_value) override { TestBasicOperations(capabilities()); } @@ -95,7 +96,7 @@ class FakeCapabilityManagerComplex : public DeviceCapabilities::Validator { // OnCapabilitiesChanged() without encountering deadlocks/unexpected behavior. class FakeCapabilitiesObserver : public DeviceCapabilities::Observer { public: - FakeCapabilitiesObserver(DeviceCapabilities* capabilities) + explicit FakeCapabilitiesObserver(DeviceCapabilities* capabilities) : capabilities_(capabilities), removed_as_observer(false) { capabilities_->AddCapabilitiesObserver(this); } @@ -135,35 +136,35 @@ class MockCapabilitiesObserver : public DeviceCapabilities::Observer { // Test fixtures needs an example default capability to test DeviceCapabilities // methods. Gets a sample key and initial value. void GetSampleDefaultCapability(std::string* key, - scoped_ptr<base::Value>* init_value) { + std::unique_ptr<base::Value>* init_value) { DCHECK(key); DCHECK(init_value); *key = DeviceCapabilities::kKeyBluetoothSupported; - *init_value = make_scoped_ptr(new base::FundamentalValue(true)); + *init_value = base::WrapUnique(new base::FundamentalValue(true)); } // For test fixtures that test dynamic capabilities, gets a sample key // and initial value. void GetSampleDynamicCapability(std::string* key, - scoped_ptr<base::Value>* init_value) { + std::unique_ptr<base::Value>* init_value) { DCHECK(key); DCHECK(init_value); *key = "dummy_dynamic_key"; - *init_value = make_scoped_ptr(new base::FundamentalValue(99)); + *init_value = base::WrapUnique(new base::FundamentalValue(99)); } // Gets a value for sample default capability different from |init_value| // returned in GetSampleDefaultCapability(). Must be of same type as // |init_value| of course. -scoped_ptr<base::Value> GetSampleDefaultCapabilityNewValue() { - return make_scoped_ptr(new base::FundamentalValue(false)); +std::unique_ptr<base::Value> GetSampleDefaultCapabilityNewValue() { + return base::WrapUnique(new base::FundamentalValue(false)); } // Gets a value for sample dynamic capability different from |init_value| // returned in GetSampleDynamicCapability(). Must be of same type as // |init_value| of course. -scoped_ptr<base::Value> GetSampleDynamicCapabilityNewValue() { - return make_scoped_ptr(new base::FundamentalValue(100)); +std::unique_ptr<base::Value> GetSampleDynamicCapabilityNewValue() { + return base::WrapUnique(new base::FundamentalValue(100)); } // Tests that |json| string matches contents of a DictionaryValue with one entry @@ -173,7 +174,7 @@ bool JsonStringEquals(const std::string& json, const base::Value& value) { base::DictionaryValue dict_value; dict_value.Set(key, value.CreateDeepCopy()); - scoped_ptr<const std::string> dict_json(SerializeToJson(dict_value)); + std::unique_ptr<const std::string> dict_json(SerializeToJson(dict_value)); return dict_json.get() && *dict_json == json; } @@ -185,7 +186,7 @@ bool JsonStringEquals(const std::string& json, // class before this function is called. void TestBasicOperations(DeviceCapabilities* capabilities) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); ASSERT_FALSE(capabilities->GetCapability(key)); @@ -204,7 +205,7 @@ void TestBasicOperations(DeviceCapabilities* capabilities) { // Write capability again. Provides way of checking that this function // ran and was successful. - scoped_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); + std::unique_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); capabilities->SetCapability(key, std::move(new_value)); } @@ -212,11 +213,11 @@ void TestBasicOperations(DeviceCapabilities* capabilities) { void AssertBasicOperationsSuccessful(const DeviceCapabilities* capabilities) { base::RunLoop().RunUntilIdle(); std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); - scoped_ptr<base::Value> value = capabilities->GetCapability(key); + std::unique_ptr<base::Value> value = capabilities->GetCapability(key); ASSERT_TRUE(value); - scoped_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); + std::unique_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); EXPECT_TRUE(base::Value::Equals(value.get(), new_value.get())); } @@ -253,14 +254,14 @@ class DeviceCapabilitiesImplTest : public ::testing::Test { } private: - scoped_ptr<base::MessageLoop> message_loop_; - scoped_ptr<DeviceCapabilities> capabilities_; - scoped_ptr<MockCapabilitiesObserver> mock_capabilities_observer_; + std::unique_ptr<base::MessageLoop> message_loop_; + std::unique_ptr<DeviceCapabilities> capabilities_; + std::unique_ptr<MockCapabilitiesObserver> mock_capabilities_observer_; }; // Tests that class is in correct state after Create(). TEST_F(DeviceCapabilitiesImplTest, Create) { - scoped_ptr<const std::string> empty_dict_string( + std::unique_ptr<const std::string> empty_dict_string( SerializeToJson(base::DictionaryValue())); EXPECT_EQ(capabilities()->GetData()->json_string(), *empty_dict_string); EXPECT_TRUE(capabilities()->GetData()->dictionary().empty()); @@ -269,14 +270,14 @@ TEST_F(DeviceCapabilitiesImplTest, Create) { // Tests Register() of a default capability. TEST_F(DeviceCapabilitiesImplTest, Register) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); EXPECT_CALL(*capabilities_observer(), OnCapabilitiesChanged(key)).Times(0); FakeCapabilityManagerSimple manager(capabilities(), key, nullptr, true); EXPECT_EQ(capabilities()->GetValidator(key), &manager); - scoped_ptr<const std::string> empty_dict_string( + std::unique_ptr<const std::string> empty_dict_string( SerializeToJson(base::DictionaryValue())); EXPECT_EQ(capabilities()->GetData()->json_string(), *empty_dict_string); EXPECT_FALSE(capabilities()->GetCapability(key)); @@ -285,7 +286,7 @@ TEST_F(DeviceCapabilitiesImplTest, Register) { // Tests Unregister() of a default capability. TEST_F(DeviceCapabilitiesImplTest, Unregister) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); EXPECT_CALL(*capabilities_observer(), OnCapabilitiesChanged(key)).Times(0); @@ -295,7 +296,7 @@ TEST_F(DeviceCapabilitiesImplTest, Unregister) { delete manager; EXPECT_FALSE(capabilities()->GetValidator(key)); - scoped_ptr<const std::string> empty_dict_string( + std::unique_ptr<const std::string> empty_dict_string( SerializeToJson(base::DictionaryValue())); EXPECT_EQ(capabilities()->GetData()->json_string(), *empty_dict_string); EXPECT_FALSE(capabilities()->GetCapability(key)); @@ -304,7 +305,7 @@ TEST_F(DeviceCapabilitiesImplTest, Unregister) { // Tests GetCapability() and updating the value through SetCapability(). TEST_F(DeviceCapabilitiesImplTest, GetCapabilityAndSetCapability) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); FakeCapabilityManagerSimple manager(capabilities(), key, init_value->CreateDeepCopy(), true); @@ -312,7 +313,7 @@ TEST_F(DeviceCapabilitiesImplTest, GetCapabilityAndSetCapability) { EXPECT_TRUE(base::Value::Equals(capabilities()->GetCapability(key).get(), init_value.get())); - scoped_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); + std::unique_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); capabilities()->SetCapability(key, new_value->CreateDeepCopy()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(base::Value::Equals(capabilities()->GetCapability(key).get(), @@ -323,12 +324,12 @@ TEST_F(DeviceCapabilitiesImplTest, GetCapabilityAndSetCapability) { TEST_F(DeviceCapabilitiesImplTest, BluetoothSupportedAndSetCapability) { FakeCapabilityManagerSimple manager( capabilities(), DeviceCapabilities::kKeyBluetoothSupported, - make_scoped_ptr(new base::FundamentalValue(true)), true); + base::WrapUnique(new base::FundamentalValue(true)), true); EXPECT_TRUE(capabilities()->BluetoothSupported()); capabilities()->SetCapability( DeviceCapabilities::kKeyBluetoothSupported, - make_scoped_ptr(new base::FundamentalValue(false))); + base::WrapUnique(new base::FundamentalValue(false))); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(capabilities()->BluetoothSupported()); } @@ -337,12 +338,12 @@ TEST_F(DeviceCapabilitiesImplTest, BluetoothSupportedAndSetCapability) { TEST_F(DeviceCapabilitiesImplTest, DisplaySupportedAndSetCapability) { FakeCapabilityManagerSimple manager( capabilities(), DeviceCapabilities::kKeyDisplaySupported, - make_scoped_ptr(new base::FundamentalValue(true)), true); + base::WrapUnique(new base::FundamentalValue(true)), true); EXPECT_TRUE(capabilities()->DisplaySupported()); capabilities()->SetCapability( DeviceCapabilities::kKeyDisplaySupported, - make_scoped_ptr(new base::FundamentalValue(false))); + base::WrapUnique(new base::FundamentalValue(false))); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(capabilities()->DisplaySupported()); } @@ -351,12 +352,12 @@ TEST_F(DeviceCapabilitiesImplTest, DisplaySupportedAndSetCapability) { TEST_F(DeviceCapabilitiesImplTest, HiResAudioSupportedAndSetCapability) { FakeCapabilityManagerSimple manager( capabilities(), DeviceCapabilities::kKeyHiResAudioSupported, - make_scoped_ptr(new base::FundamentalValue(true)), true); + base::WrapUnique(new base::FundamentalValue(true)), true); EXPECT_TRUE(capabilities()->HiResAudioSupported()); capabilities()->SetCapability( DeviceCapabilities::kKeyHiResAudioSupported, - make_scoped_ptr(new base::FundamentalValue(false))); + base::WrapUnique(new base::FundamentalValue(false))); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(capabilities()->HiResAudioSupported()); } @@ -365,7 +366,7 @@ TEST_F(DeviceCapabilitiesImplTest, HiResAudioSupportedAndSetCapability) { // rejects the proposed change. TEST_F(DeviceCapabilitiesImplTest, SetCapabilityInvalid) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); FakeCapabilityManagerSimple manager(capabilities(), key, init_value->CreateDeepCopy(), false); @@ -380,7 +381,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityInvalid) { // Test that SetCapability() updates the capabilities string correctly TEST_F(DeviceCapabilitiesImplTest, SetCapabilityUpdatesString) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); FakeCapabilityManagerSimple manager(capabilities(), key, init_value->CreateDeepCopy(), true); @@ -388,7 +389,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityUpdatesString) { EXPECT_TRUE(JsonStringEquals(capabilities()->GetData()->json_string(), key, *init_value)); - scoped_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); + std::unique_ptr<base::Value> new_value = GetSampleDefaultCapabilityNewValue(); capabilities()->SetCapability(key, new_value->CreateDeepCopy()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(JsonStringEquals(capabilities()->GetData()->json_string(), key, @@ -399,7 +400,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityUpdatesString) { // changes TEST_F(DeviceCapabilitiesImplTest, SetCapabilityNotifiesObservers) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDefaultCapability(&key, &init_value); EXPECT_CALL(*capabilities_observer(), OnCapabilitiesChanged(key)).Times(3); @@ -422,7 +423,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityNotifiesObservers) { // Test adding dynamic capabilities TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDynamic) { std::string key; - scoped_ptr<base::Value> init_value; + std::unique_ptr<base::Value> init_value; GetSampleDynamicCapability(&key, &init_value); ASSERT_FALSE(capabilities()->GetCapability(key)); @@ -434,7 +435,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDynamic) { EXPECT_TRUE(JsonStringEquals(capabilities()->GetData()->json_string(), key, *init_value)); - scoped_ptr<base::Value> new_value = GetSampleDynamicCapabilityNewValue(); + std::unique_ptr<base::Value> new_value = GetSampleDynamicCapabilityNewValue(); capabilities()->SetCapability(key, new_value->CreateDeepCopy()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(base::Value::Equals(capabilities()->GetCapability(key).get(), @@ -447,7 +448,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDynamic) { // capability of type DictionaryValue. TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionary) { std::string key("dummy_dictionary_key"); - scoped_ptr<base::Value> init_value = + std::unique_ptr<base::Value> init_value = DeserializeFromJson(kSampleDictionaryCapability); ASSERT_TRUE(init_value); FakeCapabilityManagerSimple manager(capabilities(), key, @@ -455,10 +456,10 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionary) { capabilities()->SetCapability( "dummy_dictionary_key.dummy_field_bool", - make_scoped_ptr(new base::FundamentalValue(false))); + base::WrapUnique(new base::FundamentalValue(false))); base::RunLoop().RunUntilIdle(); bool value_bool = true; - scoped_ptr<base::Value> value = + std::unique_ptr<base::Value> value = capabilities()->GetCapability("dummy_dictionary_key.dummy_field_bool"); ASSERT_TRUE(value); EXPECT_TRUE(value->GetAsBoolean(&value_bool)); @@ -466,7 +467,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionary) { capabilities()->SetCapability( "dummy_dictionary_key.dummy_field_int", - make_scoped_ptr(new base::FundamentalValue(100))); + base::WrapUnique(new base::FundamentalValue(100))); base::RunLoop().RunUntilIdle(); int value_int = 0; value = capabilities()->GetCapability("dummy_dictionary_key.dummy_field_int"); @@ -479,7 +480,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionary) { // capability of type DictionaryValue and invalid changes are proposed. TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionaryInvalid) { std::string key("dummy_dictionary_key"); - scoped_ptr<base::Value> init_value = + std::unique_ptr<base::Value> init_value = DeserializeFromJson(kSampleDictionaryCapability); ASSERT_TRUE(init_value); FakeCapabilityManagerSimple manager(capabilities(), key, @@ -487,10 +488,10 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionaryInvalid) { capabilities()->SetCapability( "dummy_dictionary_key.dummy_field_bool", - make_scoped_ptr(new base::FundamentalValue(false))); + base::WrapUnique(new base::FundamentalValue(false))); base::RunLoop().RunUntilIdle(); bool value_bool = false; - scoped_ptr<base::Value> value = + std::unique_ptr<base::Value> value = capabilities()->GetCapability("dummy_dictionary_key.dummy_field_bool"); ASSERT_TRUE(value); EXPECT_TRUE(value->GetAsBoolean(&value_bool)); @@ -498,7 +499,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionaryInvalid) { capabilities()->SetCapability( "dummy_dictionary_key.dummy_field_int", - make_scoped_ptr(new base::FundamentalValue(100))); + base::WrapUnique(new base::FundamentalValue(100))); base::RunLoop().RunUntilIdle(); int value_int = 0; value = capabilities()->GetCapability("dummy_dictionary_key.dummy_field_int"); @@ -509,7 +510,7 @@ TEST_F(DeviceCapabilitiesImplTest, SetCapabilityDictionaryInvalid) { // Test MergeDictionary. TEST_F(DeviceCapabilitiesImplTest, MergeDictionary) { - scoped_ptr<base::Value> deserialized_value = + std::unique_ptr<base::Value> deserialized_value = DeserializeFromJson(kSampleDictionaryCapability); ASSERT_TRUE(deserialized_value); base::DictionaryValue* dict_value = nullptr; @@ -521,7 +522,7 @@ TEST_F(DeviceCapabilitiesImplTest, MergeDictionary) { // First make sure that capabilities get created if they do not exist bool value_bool = false; - scoped_ptr<base::Value> value = + std::unique_ptr<base::Value> value = capabilities()->GetCapability("dummy_field_bool"); ASSERT_TRUE(value); EXPECT_TRUE(value->GetAsBoolean(&value_bool)); @@ -561,7 +562,7 @@ TEST_F(DeviceCapabilitiesImplTest, OnCapabilitiesChangedSafe) { // Trigger FakeCapabilitiesObserver::OnCapabilitiesChanged() capabilities()->SetCapability( - "dummy_trigger_key", make_scoped_ptr(new base::FundamentalValue(true))); + "dummy_trigger_key", base::WrapUnique(new base::FundamentalValue(true))); base::RunLoop().RunUntilIdle(); // Check that FakeCapabilitiesObserver::OnCapabilitiesChanged() ran and that @@ -577,7 +578,7 @@ TEST_F(DeviceCapabilitiesImplTest, ValidateSafe) { // Trigger FakeCapabilityManagerComplex::Validate() capabilities()->SetCapability( - "dummy_validate_key", make_scoped_ptr(new base::FundamentalValue(true))); + "dummy_validate_key", base::WrapUnique(new base::FundamentalValue(true))); base::RunLoop().RunUntilIdle(); // Check that FakeCapabilityManagerComplex::Validate() ran and that behavior diff --git a/chromium/chromecast/base/error_codes_unittest.cc b/chromium/chromecast/base/error_codes_unittest.cc index ef9c1924f85..42f36049078 100644 --- a/chromium/chromecast/base/error_codes_unittest.cc +++ b/chromium/chromecast/base/error_codes_unittest.cc @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chromecast/base/error_codes.h" + +#include <memory> + #include "base/base_paths.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/memory/scoped_ptr.h" #include "base/test/scoped_path_override.h" -#include "chromecast/base/error_codes.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromecast { @@ -29,7 +31,7 @@ class ErrorCodesTest : public testing::Test { private: base::ScopedTempDir fake_home_dir_; - scoped_ptr<base::ScopedPathOverride> path_override_; + std::unique_ptr<base::ScopedPathOverride> path_override_; }; TEST_F(ErrorCodesTest, GetInitialErrorCodeReturnsNoErrorIfMissingFile) { diff --git a/chromium/chromecast/base/metrics/cast_metrics_helper.cc b/chromium/chromecast/base/metrics/cast_metrics_helper.cc index 9680c8006ed..ac8b7b8f1f2 100644 --- a/chromium/chromecast/base/metrics/cast_metrics_helper.cc +++ b/chromium/chromecast/base/metrics/cast_metrics_helper.cc @@ -4,14 +4,21 @@ #include "chromecast/base/metrics/cast_metrics_helper.h" +#include <memory> +#include <string> +#include <vector> + #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/json/json_string_value_serializer.h" #include "base/location.h" #include "base/metrics/histogram.h" #include "base/metrics/user_metrics.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/time/time.h" +#include "base/values.h" #include "chromecast/base/metrics/cast_histograms.h" #include "chromecast/base/metrics/grouped_histogram.h" @@ -33,6 +40,14 @@ CastMetricsHelper* g_instance = NULL; const char kMetricsNameAppInfoDelimiter = '#'; +std::unique_ptr<std::string> SerializeToJson(const base::Value& value) { + std::unique_ptr<std::string> json_str(new std::string()); + JSONStringValueSerializer serializer(json_str.get()); + if (!serializer.Serialize(value)) + json_str.reset(nullptr); + return json_str; +} + } // namespace // static @@ -91,7 +106,6 @@ CastMetricsHelper* CastMetricsHelper::GetInstance() { CastMetricsHelper::CastMetricsHelper( scoped_refptr<base::SingleThreadTaskRunner> task_runner) : task_runner_(task_runner), - session_id_("00000000000000000000000000000000"), metrics_sink_(NULL), logged_first_audio_(false), record_action_callback_(base::Bind(&base::RecordComputedAction)) { @@ -227,6 +241,11 @@ void CastMetricsHelper::SetRecordActionCallback( record_action_callback_ = callback; } +void CastMetricsHelper::SetDummySessionIdForTesting() { + DCHECK(task_runner_->BelongsToCurrentThread()); + session_id_ = "00000000-0000-0000-0000-000000000000"; +} + void CastMetricsHelper::RecordSimpleAction(const std::string& action) { MAKE_SURE_THREAD(RecordSimpleAction, action); @@ -272,5 +291,34 @@ void CastMetricsHelper::LogMediumTimeHistogramEvent( 50); } +void CastMetricsHelper::RecordApplicationEvent(const std::string& event) { + std::unique_ptr<base::DictionaryValue> cast_event( + new base::DictionaryValue()); + cast_event->SetString("name", event); + base::TimeTicks now = base::TimeTicks::Now(); + cast_event->SetDouble("time", now.ToInternalValue()); + cast_event->SetString("app_id", app_id_); + cast_event->SetString("session_id", session_id_); + cast_event->SetString("sdk_version", sdk_version_); + const std::string message = *SerializeToJson(*cast_event.get()).get(); + RecordSimpleAction(message); +} + +void CastMetricsHelper::RecordApplicationEventWithValue( + const std::string& event, + int value) { + std::unique_ptr<base::DictionaryValue> cast_event( + new base::DictionaryValue()); + cast_event->SetString("name", event); + base::TimeTicks now = base::TimeTicks::Now(); + cast_event->SetDouble("time", now.ToInternalValue()); + cast_event->SetString("app_id", app_id_); + cast_event->SetString("session_id", session_id_); + cast_event->SetString("sdk_version", sdk_version_); + cast_event->SetInteger("value", value); + const std::string message = *SerializeToJson(*cast_event.get()).get(); + RecordSimpleAction(message); +} + } // namespace metrics } // namespace chromecast diff --git a/chromium/chromecast/base/metrics/cast_metrics_helper.h b/chromium/chromecast/base/metrics/cast_metrics_helper.h index 43f9f7ed45f..e4b6c6f4a11 100644 --- a/chromium/chromecast/base/metrics/cast_metrics_helper.h +++ b/chromium/chromecast/base/metrics/cast_metrics_helper.h @@ -77,6 +77,11 @@ class CastMetricsHelper { // This is used as an in-place replacement of content::RecordComputedAction(). virtual void RecordSimpleAction(const std::string& action); + // Logs application specific events. + virtual void RecordApplicationEvent(const std::string& event); + virtual void RecordApplicationEventWithValue(const std::string& event, + int value); + // Logs UMA record of the time the app made its first paint. virtual void LogTimeToFirstPaint(); @@ -104,6 +109,9 @@ class CastMetricsHelper { // CastMetricsHelper only honors the last one. virtual void SetRecordActionCallback(const RecordActionCallback& callback); + // Sets an all-0's session ID for running browser tests. + void SetDummySessionIdForTesting(); + protected: // Creates a CastMetricsHelper instance with no task runner. This should only // be used by tests, since invoking any non-overridden methods on this diff --git a/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc b/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc index 043957fbe85..d0ed02a46d4 100644 --- a/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc +++ b/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc @@ -29,6 +29,7 @@ class CastMetricsHelperStub : public CastMetricsHelper { std::string GetMetricsNameWithAppName( const std::string& prefix, const std::string& suffix) const override; void SetMetricsSink(MetricsSink* delegate) override; + void RecordSimpleAction(const std::string& action) override; private: DISALLOW_COPY_AND_ASSIGN(CastMetricsHelperStub); @@ -79,6 +80,9 @@ void CastMetricsHelperStub::SetMetricsSink(MetricsSink* delegate) { } // namespace +void CastMetricsHelperStub::RecordSimpleAction(const std::string& action) { +} + void InitializeMetricsHelperForTesting() { if (!stub_instance_exists) { new CastMetricsHelperStub(); diff --git a/chromium/chromecast/base/metrics/grouped_histogram.cc b/chromium/chromecast/base/metrics/grouped_histogram.cc index 4d84929aea8..1101a7992c5 100644 --- a/chromium/chromecast/base/metrics/grouped_histogram.cc +++ b/chromium/chromecast/base/metrics/grouped_histogram.cc @@ -42,7 +42,7 @@ struct HistogramArgs { const char* name; int minimum; int maximum; - size_t bucket_count; + uint32_t bucket_count; }; // List of metrics to collect using a GroupedHistogram. @@ -123,7 +123,7 @@ class GroupedHistogram : public base::Histogram { std::string metric_to_group_; Sample minimum_; Sample maximum_; - size_t bucket_count_; + uint32_t bucket_count_; DISALLOW_COPY_AND_ASSIGN(GroupedHistogram); }; @@ -135,7 +135,7 @@ class GroupedHistogram : public base::Histogram { void PreregisterHistogram(const std::string& name, GroupedHistogram::Sample minimum, GroupedHistogram::Sample maximum, - size_t bucket_count, + uint32_t bucket_count, int32_t flags) { DCHECK(base::StatisticsRecorder::IsActive()); DCHECK(base::Histogram::InspectConstructionArguments( diff --git a/chromium/chromecast/base/serializers.cc b/chromium/chromecast/base/serializers.cc index 87e9dc51cef..7041a961de8 100644 --- a/chromium/chromecast/base/serializers.cc +++ b/chromium/chromecast/base/serializers.cc @@ -10,12 +10,12 @@ namespace chromecast { -scoped_ptr<base::Value> DeserializeFromJson(const std::string& text) { +std::unique_ptr<base::Value> DeserializeFromJson(const std::string& text) { JSONStringValueDeserializer deserializer(text); int error_code = -1; std::string error_msg; - scoped_ptr<base::Value> value = + std::unique_ptr<base::Value> value = deserializer.Deserialize(&error_code, &error_msg); DLOG_IF(ERROR, !value) << "JSON error " << error_code << ":" << error_msg; @@ -23,20 +23,21 @@ scoped_ptr<base::Value> DeserializeFromJson(const std::string& text) { return value; } -scoped_ptr<std::string> SerializeToJson(const base::Value& value) { - scoped_ptr<std::string> json_str(new std::string()); +std::unique_ptr<std::string> SerializeToJson(const base::Value& value) { + std::unique_ptr<std::string> json_str(new std::string()); JSONStringValueSerializer serializer(json_str.get()); if (!serializer.Serialize(value)) json_str.reset(nullptr); return json_str; } -scoped_ptr<base::Value> DeserializeJsonFromFile(const base::FilePath& path) { +std::unique_ptr<base::Value> DeserializeJsonFromFile( + const base::FilePath& path) { JSONFileValueDeserializer deserializer(path); int error_code = -1; std::string error_msg; - scoped_ptr<base::Value> value = + std::unique_ptr<base::Value> value = deserializer.Deserialize(&error_code, &error_msg); DLOG_IF(ERROR, !value) << "JSON error " << error_code << ":" << error_msg; diff --git a/chromium/chromecast/base/serializers.h b/chromium/chromecast/base/serializers.h index 06c79b76067..df648feed65 100644 --- a/chromium/chromecast/base/serializers.h +++ b/chromium/chromecast/base/serializers.h @@ -5,9 +5,9 @@ #ifndef CHROMECAST_BASE_SERIALIZERS_H_ #define CHROMECAST_BASE_SERIALIZERS_H_ +#include <memory> #include <string> -#include "base/memory/scoped_ptr.h" namespace base { class Value; @@ -19,16 +19,17 @@ namespace chromecast { // Helper function which deserializes JSON |text| into a base::Value. If |text| // is empty, is not valid JSON, or if some other deserialization error occurs, // the return value will hold the NULL pointer. -scoped_ptr<base::Value> DeserializeFromJson(const std::string& text); +std::unique_ptr<base::Value> DeserializeFromJson(const std::string& text); // Helper function which serializes |value| into a JSON string. If a // serialization error occurs,the return value will hold the NULL pointer. -scoped_ptr<std::string> SerializeToJson(const base::Value& value); +std::unique_ptr<std::string> SerializeToJson(const base::Value& value); // Helper function which deserializes JSON file at |path| into a base::Value. // If file in |path| is empty, is not valid JSON, or if some other // deserialization error occurs, the return value will hold the NULL pointer. -scoped_ptr<base::Value> DeserializeJsonFromFile(const base::FilePath& path); +std::unique_ptr<base::Value> DeserializeJsonFromFile( + const base::FilePath& path); // Helper function which serializes |value| into the file at |path|. The // function returns true on success, false otherwise. diff --git a/chromium/chromecast/base/serializers_unittest.cc b/chromium/chromecast/base/serializers_unittest.cc index 5724b4b0b79..d5c4189a7b7 100644 --- a/chromium/chromecast/base/serializers_unittest.cc +++ b/chromium/chromecast/base/serializers_unittest.cc @@ -30,37 +30,37 @@ const char kTestValue[] = "test_value"; TEST(DeserializeFromJson, EmptyString) { std::string str; - scoped_ptr<base::Value> value = DeserializeFromJson(str); + std::unique_ptr<base::Value> value = DeserializeFromJson(str); EXPECT_EQ(nullptr, value.get()); } TEST(DeserializeFromJson, EmptyJsonObject) { std::string str = kEmptyJsonString; - scoped_ptr<base::Value> value = DeserializeFromJson(str); + std::unique_ptr<base::Value> value = DeserializeFromJson(str); EXPECT_NE(nullptr, value.get()); } TEST(DeserializeFromJson, ProperJsonObject) { std::string str = kProperJsonString; - scoped_ptr<base::Value> value = DeserializeFromJson(str); + std::unique_ptr<base::Value> value = DeserializeFromJson(str); EXPECT_NE(nullptr, value.get()); } TEST(DeserializeFromJson, PoorlyFormedJsonObject) { std::string str = kPoorlyFormedJsonString; - scoped_ptr<base::Value> value = DeserializeFromJson(str); + std::unique_ptr<base::Value> value = DeserializeFromJson(str); EXPECT_EQ(nullptr, value.get()); } TEST(SerializeToJson, BadValue) { - base::BinaryValue value(scoped_ptr<char[]>(new char[12]), 12); - scoped_ptr<std::string> str = SerializeToJson(value); + base::BinaryValue value(std::unique_ptr<char[]>(new char[12]), 12); + std::unique_ptr<std::string> str = SerializeToJson(value); EXPECT_EQ(nullptr, str.get()); } TEST(SerializeToJson, EmptyValue) { base::DictionaryValue value; - scoped_ptr<std::string> str = SerializeToJson(value); + std::unique_ptr<std::string> str = SerializeToJson(value); ASSERT_NE(nullptr, str.get()); EXPECT_EQ(kEmptyJsonString, *str); } @@ -68,16 +68,16 @@ TEST(SerializeToJson, EmptyValue) { TEST(SerializeToJson, PopulatedValue) { base::DictionaryValue orig_value; orig_value.SetString(kTestKey, kTestValue); - scoped_ptr<std::string> str = SerializeToJson(orig_value); + std::unique_ptr<std::string> str = SerializeToJson(orig_value); ASSERT_NE(nullptr, str.get()); - scoped_ptr<base::Value> new_value = DeserializeFromJson(*str); + std::unique_ptr<base::Value> new_value = DeserializeFromJson(*str); ASSERT_NE(nullptr, new_value.get()); EXPECT_TRUE(new_value->Equals(&orig_value)); } TEST(DeserializeJsonFromFile, NoFile) { - scoped_ptr<base::Value> value = + std::unique_ptr<base::Value> value = DeserializeJsonFromFile(base::FilePath("/file/does/not/exist.json")); EXPECT_EQ(nullptr, value.get()); } @@ -85,7 +85,7 @@ TEST(DeserializeJsonFromFile, NoFile) { TEST(DeserializeJsonFromFile, EmptyString) { ScopedTempFile temp; EXPECT_EQ(static_cast<int>(strlen("")), temp.Write("")); - scoped_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); + std::unique_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); EXPECT_EQ(nullptr, value.get()); } @@ -93,7 +93,7 @@ TEST(DeserializeJsonFromFile, EmptyJsonObject) { ScopedTempFile temp; EXPECT_EQ(static_cast<int>(strlen(kEmptyJsonString)), temp.Write(kEmptyJsonString)); - scoped_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); + std::unique_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); EXPECT_NE(nullptr, value.get()); } @@ -101,7 +101,7 @@ TEST(DeserializeJsonFromFile, ProperJsonObject) { ScopedTempFile temp; EXPECT_EQ(static_cast<int>(strlen(kProperJsonString)), temp.Write(kProperJsonString)); - scoped_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); + std::unique_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); EXPECT_NE(nullptr, value.get()); } @@ -109,14 +109,14 @@ TEST(DeserializeJsonFromFile, PoorlyFormedJsonObject) { ScopedTempFile temp; EXPECT_EQ(static_cast<int>(strlen(kPoorlyFormedJsonString)), temp.Write(kPoorlyFormedJsonString)); - scoped_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); + std::unique_ptr<base::Value> value = DeserializeJsonFromFile(temp.path()); EXPECT_EQ(nullptr, value.get()); } TEST(SerializeJsonToFile, BadValue) { ScopedTempFile temp; - base::BinaryValue value(scoped_ptr<char[]>(new char[12]), 12); + base::BinaryValue value(std::unique_ptr<char[]>(new char[12]), 12); ASSERT_FALSE(SerializeJsonToFile(temp.path(), value)); std::string str(temp.Read()); EXPECT_TRUE(str.empty()); @@ -141,7 +141,7 @@ TEST(SerializeJsonToFile, PopulatedValue) { std::string str(temp.Read()); ASSERT_FALSE(str.empty()); - scoped_ptr<base::Value> new_value = DeserializeJsonFromFile(temp.path()); + std::unique_ptr<base::Value> new_value = DeserializeJsonFromFile(temp.path()); ASSERT_NE(nullptr, new_value.get()); EXPECT_TRUE(new_value->Equals(&orig_value)); } diff --git a/chromium/chromecast/base/system_time_change_notifier_unittest.cc b/chromium/chromecast/base/system_time_change_notifier_unittest.cc index 7a4ad956bb3..142a17e0504 100644 --- a/chromium/chromecast/base/system_time_change_notifier_unittest.cc +++ b/chromium/chromecast/base/system_time_change_notifier_unittest.cc @@ -4,6 +4,8 @@ #include "chromecast/base/system_time_change_notifier.h" +#include <memory> + #include "base/bind.h" #include "base/location.h" #include "base/macros.h" @@ -85,9 +87,9 @@ class SystemTimeChangeNotifierTest : public testing::Test { run_loop.Run(); } - scoped_ptr<base::MessageLoop> message_loop_; - scoped_ptr<SystemTimeChangeNotifierPeriodicMonitor> notifier_; - scoped_ptr<TimeChangeObserver> observer_; + std::unique_ptr<base::MessageLoop> message_loop_; + std::unique_ptr<SystemTimeChangeNotifierPeriodicMonitor> notifier_; + std::unique_ptr<TimeChangeObserver> observer_; }; TEST_F(SystemTimeChangeNotifierTest, NotChanged) { |