Update from https://crrev.com/316786
List of manually-modified files:
gpu/command_buffer/service/in_process_command_buffer.cc
examples/sample_app/BUILD.gn
examples/sample_app/spinning_cube.cc
mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java
mojo/cc/context_provider_mojo.cc
mojo/cc/context_provider_mojo.h
mojo/common/trace_controller_impl.cc
mojo/gles2/command_buffer_client_impl.cc
mojo/gles2/command_buffer_client_impl.h
services/gles2/gpu_impl.cc
shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
sky/engine/core/dom/Node.cpp
sky/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java
ui/events/latency_info.cc
ui/gfx/transform.cc
ui/gfx/transform.h
ui/gfx/transform_util.cc
ui/gfx/transform_util.h
Review URL: https://codereview.chromium.org/935333002
diff --git a/BUILD.gn b/BUILD.gn
index 44e656c..e417681 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -11,12 +11,6 @@
component("base") {
sources = [
- "third_party/dmg_fp/dmg_fp.h",
- "third_party/dmg_fp/g_fmt.cc",
- "third_party/dmg_fp/dtoa_wrapper.cc",
- "third_party/icu/icu_utf.cc",
- "third_party/icu/icu_utf.h",
- "third_party/superfasthash/superfasthash.c",
"allocator/allocator_extension.cc",
"allocator/allocator_extension.h",
"allocator/type_profiler_control.cc",
@@ -94,6 +88,8 @@
"auto_reset.h",
"barrier_closure.cc",
"barrier_closure.h",
+ "base64.cc",
+ "base64.h",
"base_export.h",
"base_paths.cc",
"base_paths.h",
@@ -106,8 +102,6 @@
"base_paths_win.cc",
"base_paths_win.h",
"base_switches.h",
- "base64.cc",
- "base64.h",
"basictypes.h",
"big_endian.cc",
"big_endian.h",
@@ -125,10 +119,10 @@
"callback_internal.cc",
"callback_internal.h",
"cancelable_callback.h",
- "command_line.cc",
- "command_line.h",
"chromeos/memory_pressure_observer_chromeos.cc",
"chromeos/memory_pressure_observer_chromeos.h",
+ "command_line.cc",
+ "command_line.h",
"compiler_specific.h",
"containers/adapters.h",
"containers/hash_tables.h",
@@ -154,6 +148,12 @@
"debug/dump_without_crashing.h",
"debug/gdi_debug_util_win.cc",
"debug/gdi_debug_util_win.h",
+ "third_party/dmg_fp/dmg_fp.h",
+ "third_party/dmg_fp/dtoa_wrapper.cc",
+ "third_party/dmg_fp/g_fmt.cc",
+ "third_party/icu/icu_utf.cc",
+ "third_party/icu/icu_utf.h",
+ "third_party/superfasthash/superfasthash.c",
# This file depends on files from the "allocator" target,
# but this target does not depend on "allocator" (see
@@ -185,8 +185,6 @@
"files/dir_reader_linux.h",
"files/dir_reader_posix.h",
"files/file.cc",
- "files/file_posix.cc",
- "files/file_win.cc",
"files/file_enumerator.cc",
"files/file_enumerator.h",
"files/file_enumerator_posix.cc",
@@ -203,6 +201,7 @@
"files/file_path_watcher_linux.cc",
"files/file_path_watcher_mac.cc",
"files/file_path_watcher_win.cc",
+ "files/file_posix.cc",
"files/file_proxy.cc",
"files/file_proxy.h",
"files/file_util.cc",
@@ -214,6 +213,7 @@
"files/file_util_proxy.cc",
"files/file_util_proxy.h",
"files/file_util_win.cc",
+ "files/file_win.cc",
"files/important_file_writer.cc",
"files/important_file_writer.h",
"files/memory_mapped_file.cc",
@@ -280,8 +280,8 @@
"mac/launchd.h",
"mac/libdispatch_task_runner.cc",
"mac/libdispatch_task_runner.h",
- "mac/mac_logging.h",
"mac/mac_logging.cc",
+ "mac/mac_logging.h",
"mac/mac_util.h",
"mac/mac_util.mm",
"mac/mach_logging.cc",
@@ -378,19 +378,19 @@
"message_loop/message_pump_mac.mm",
"message_loop/message_pump_win.cc",
"message_loop/message_pump_win.h",
- "metrics/field_trial.cc",
- "metrics/field_trial.h",
- "metrics/sample_map.cc",
- "metrics/sample_map.h",
- "metrics/sample_vector.cc",
- "metrics/sample_vector.h",
"metrics/bucket_ranges.cc",
"metrics/bucket_ranges.h",
+ "metrics/field_trial.cc",
+ "metrics/field_trial.h",
"metrics/histogram.cc",
"metrics/histogram.h",
"metrics/histogram_base.cc",
"metrics/histogram_base.h",
"metrics/histogram_delta_serialization.cc",
+ "metrics/sample_map.cc",
+ "metrics/sample_map.h",
+ "metrics/sample_vector.cc",
+ "metrics/sample_vector.h",
"metrics/histogram_delta_serialization.",
"metrics/histogram_flattener.h",
"metrics/histogram_macros.h",
@@ -402,10 +402,6 @@
"metrics/sparse_histogram.h",
"metrics/statistics_recorder.cc",
"metrics/statistics_recorder.h",
- "metrics/stats_counters.cc",
- "metrics/stats_counters.h",
- "metrics/stats_table.cc",
- "metrics/stats_table.h",
"metrics/user_metrics.cc",
"metrics/user_metrics.h",
"metrics/user_metrics_action.h",
@@ -414,14 +410,14 @@
"native_library_mac.mm",
"native_library_posix.cc",
"native_library_win.cc",
- "numerics/safe_conversions.h",
- "numerics/safe_conversions_impl.h",
- "numerics/safe_math.h",
- "numerics/safe_math_impl.h",
"nix/mime_util_xdg.cc",
"nix/mime_util_xdg.h",
"nix/xdg_util.cc",
"nix/xdg_util.h",
+ "numerics/safe_conversions.h",
+ "numerics/safe_conversions_impl.h",
+ "numerics/safe_math.h",
+ "numerics/safe_math_impl.h",
"observer_list.h",
"observer_list_threadsafe.h",
"os_compat_android.cc",
@@ -544,11 +540,11 @@
"strings/string16.cc",
"strings/string16.h",
"strings/string_number_conversions.cc",
- "strings/string_split.cc",
- "strings/string_split.h",
"strings/string_number_conversions.h",
"strings/string_piece.cc",
"strings/string_piece.h",
+ "strings/string_split.cc",
+ "strings/string_split.h",
"strings/string_tokenizer.h",
"strings/string_util.cc",
"strings/string_util.h",
@@ -590,8 +586,6 @@
"synchronization/waitable_event_watcher_posix.cc",
"synchronization/waitable_event_watcher_win.cc",
"synchronization/waitable_event_win.cc",
- "system_monitor/system_monitor.cc",
- "system_monitor/system_monitor.h",
"sys_byteorder.h",
"sys_info.cc",
"sys_info.h",
@@ -604,6 +598,8 @@
"sys_info_openbsd.cc",
"sys_info_posix.cc",
"sys_info_win.cc",
+ "system_monitor/system_monitor.cc",
+ "system_monitor/system_monitor.h",
"task/cancelable_task_tracker.cc",
"task/cancelable_task_tracker.h",
"task_runner.cc",
@@ -644,12 +640,12 @@
"threading/thread_local_storage_posix.cc",
"threading/thread_local_storage_win.cc",
"threading/thread_local_win.cc",
- "threading/thread_restrictions.h",
"threading/thread_restrictions.cc",
+ "threading/thread_restrictions.h",
"threading/watchdog.cc",
"threading/watchdog.h",
- "threading/worker_pool.h",
"threading/worker_pool.cc",
+ "threading/worker_pool.h",
"threading/worker_pool_posix.cc",
"threading/worker_pool_posix.h",
"threading/worker_pool_win.cc",
@@ -675,6 +671,11 @@
"timer/mock_timer.h",
"timer/timer.cc",
"timer/timer.h",
+ "trace_event/memory_dump_manager.cc",
+ "trace_event/memory_dump_manager.h",
+ "trace_event/memory_dump_provider.h",
+ "trace_event/process_memory_dump.cc",
+ "trace_event/process_memory_dump.h",
"trace_event/trace_event.h",
"trace_event/trace_event_android.cc",
"trace_event/trace_event_argument.cc",
@@ -695,10 +696,10 @@
"tracking_info.cc",
"tracking_info.h",
"tuple.h",
- "values.cc",
- "values.h",
"value_conversions.cc",
"value_conversions.h",
+ "values.cc",
+ "values.h",
"version.cc",
"version.h",
"vlog.cc",
@@ -787,10 +788,10 @@
if (is_android) {
sources += [
- "memory/discardable_memory_ashmem_allocator.cc",
- "memory/discardable_memory_ashmem_allocator.h",
"memory/discardable_memory_ashmem.cc",
"memory/discardable_memory_ashmem.h",
+ "memory/discardable_memory_ashmem_allocator.cc",
+ "memory/discardable_memory_ashmem_allocator.h",
]
sources -= [
"base_paths_posix.cc",
@@ -802,12 +803,12 @@
sources += [
"debug/proc_maps_linux.cc",
"files/file_path_watcher_linux.cc",
- "process/memory_linux.cc",
+ "posix/unix_domain_socket_linux.cc",
"process/internal_linux.cc",
+ "process/memory_linux.cc",
"process/process_handle_linux.cc",
"process/process_iterator_linux.cc",
"process/process_metrics_linux.cc",
- "posix/unix_domain_socket_linux.cc",
"sys_info_linux.cc",
]
set_sources_assignment_filter(sources_assignment_filter)
@@ -835,24 +836,24 @@
"debug/stack_trace_posix.cc",
"files/file_enumerator_posix.cc",
"files/file_util_posix.cc",
+ "memory/shared_memory_posix.cc",
"message_loop/message_pump_libevent.cc",
+ "metrics/field_trial.cc",
+ "native_library_posix.cc",
"process/kill_posix.cc",
"process/launch_posix.cc",
"process/process_metrics_posix.cc",
"process/process_posix.cc",
- "metrics/field_trial.cc",
- "native_library_posix.cc",
- "memory/shared_memory_posix.cc",
"sync_socket_posix.cc",
"sys_info_posix.cc",
]
} else {
# Remove nacl stuff.
sources -= [
+ "memory/shared_memory_nacl.cc",
"os_compat_nacl.cc",
"os_compat_nacl.h",
"rand_util_nacl.cc",
- "memory/shared_memory_nacl.cc",
]
}
@@ -1126,6 +1127,10 @@
sources = [
"files/protect_file_posix.cc",
]
+
+ deps = [
+ "//base",
+ ]
}
test("base_unittests") {
@@ -1183,10 +1188,9 @@
"gmock_unittest.cc",
"guid_unittest.cc",
"hash_unittest.cc",
- "id_map_unittest.cc",
"i18n/break_iterator_unittest.cc",
- "i18n/char_iterator_unittest.cc",
"i18n/case_conversion_unittest.cc",
+ "i18n/char_iterator_unittest.cc",
"i18n/file_util_icu_unittest.cc",
"i18n/icu_string_conversions_unittest.cc",
"i18n/number_formatting_unittest.cc",
@@ -1195,6 +1199,7 @@
"i18n/string_search_unittest.cc",
"i18n/time_formatting_unittest.cc",
"i18n/timezone_unittest.cc",
+ "id_map_unittest.cc",
"ios/device_util_unittest.mm",
"ios/weak_nsobject_unittest.mm",
"json/json_parser_unittest.cc",
@@ -1233,17 +1238,17 @@
"message_loop/message_loop_unittest.cc",
"message_loop/message_pump_glib_unittest.cc",
"message_loop/message_pump_io_ios_unittest.cc",
- "metrics/sample_map_unittest.cc",
- "metrics/sample_vector_unittest.cc",
"metrics/bucket_ranges_unittest.cc",
"metrics/field_trial_unittest.cc",
"metrics/histogram_base_unittest.cc",
"metrics/histogram_delta_serialization_unittest.cc",
"metrics/histogram_snapshot_manager_unittest.cc",
"metrics/histogram_unittest.cc",
+ "metrics/sample_map_unittest.cc",
+ "metrics/sample_vector_unittest.cc",
"metrics/sparse_histogram_unittest.cc",
- "metrics/stats_table_unittest.cc",
"metrics/statistics_recorder_unittest.cc",
+ "numerics/safe_numerics_unittest.cc",
"observer_list_unittest.cc",
"os_compat_android_unittest.cc",
"path_service_unittest.cc",
@@ -1271,7 +1276,6 @@
"process/process_util_unittest_ios.cc",
"profiler/tracked_time_unittest.cc",
"rand_util_unittest.cc",
- "numerics/safe_numerics_unittest.cc",
"scoped_clear_errno_unittest.cc",
"scoped_generic_unittest.cc",
"scoped_native_library_unittest.cc",
@@ -1282,13 +1286,13 @@
"strings/nullable_string16_unittest.cc",
"strings/safe_sprintf_unittest.cc",
"strings/string16_unittest.cc",
- "strings/stringprintf_unittest.cc",
"strings/string_number_conversions_unittest.cc",
"strings/string_piece_unittest.cc",
"strings/string_split_unittest.cc",
"strings/string_tokenizer_unittest.cc",
"strings/string_util_unittest.cc",
"strings/stringize_macros_unittest.cc",
+ "strings/stringprintf_unittest.cc",
"strings/sys_string_conversions_mac_unittest.mm",
"strings/sys_string_conversions_unittest.cc",
"strings/utf_offset_string_conversions_unittest.cc",
@@ -1330,6 +1334,7 @@
"timer/mock_timer_unittest.cc",
"timer/timer_unittest.cc",
"tools_sanity_unittest.cc",
+ "trace_event/memory_dump_manager_unittest.cc",
"trace_event/trace_event_argument_unittest.cc",
"trace_event/trace_event_memory_unittest.cc",
"trace_event/trace_event_synthetic_delay_unittest.cc",
@@ -1372,6 +1377,7 @@
"//base/test:run_all_unittests",
"//base/test:test_support",
"//base/third_party/dynamic_annotations",
+ "//base/third_party/nspr",
"//testing/gmock",
"//testing/gtest",
"//third_party/icu",
@@ -1386,7 +1392,6 @@
if (is_ios) {
sources -= [
- "metrics/stats_table_uinittest.cc", # Requires spawning a process.
"process/memory_unittest.cc",
"process/memory_unittest_mac.h",
"process/memory_unittest_mac.mm",
@@ -1509,16 +1514,19 @@
# GYP: //base.gyp:base_java_application_state
# GYP: //base.gyp:base_java_library_load_from_apk_status_codes
+ # GYP: //base.gyp:base_java_library_process_type
# GYP: //base.gyp:base_java_memory_pressure_level
java_cpp_enum("base_android_java_enums_srcjar") {
sources = [
"android/application_status_listener.h",
"android/library_loader/library_load_from_apk_status_codes.h",
+ "android/library_loader/library_loader_hooks.h",
"memory/memory_pressure_listener.h",
]
outputs = [
"org/chromium/base/ApplicationState.java",
"org/chromium/base/library_loader/LibraryLoadFromApkStatusCodes.java",
+ "org/chromium/base/library_loader/LibraryProcessType.java",
"org/chromium/base/MemoryPressureLevel.java",
]
}
diff --git a/allocator/BUILD.gn b/allocator/BUILD.gn
index 8d96317..e931b1c 100644
--- a/allocator/BUILD.gn
+++ b/allocator/BUILD.gn
@@ -46,6 +46,11 @@
source_set("tcmalloc") {
tcmalloc_dir = "//third_party/tcmalloc/chromium"
+ # Don't check tcmalloc's includes. These files include various files like
+ # base/foo.h and they actually refer to tcmalloc's forked copy of base
+ # rather than the regular one, which confuses the header checker.
+ check_includes = false
+
sources = [
# Generated for our configuration from tcmalloc"s build
# and checked in.
@@ -134,7 +139,6 @@
"$tcmalloc_dir/src/windows/port.cc",
"$tcmalloc_dir/src/windows/port.h",
"allocator_shim.cc",
- "allocator_shim.h",
"debugallocation_shim.cc",
# These are both #included by allocator_shim for maximal linking.
@@ -176,10 +180,10 @@
# cpuprofiler
"$tcmalloc_dir/src/base/thread_lister.c",
"$tcmalloc_dir/src/base/thread_lister.h",
- "$tcmalloc_dir/src/profiledata.cc",
- "$tcmalloc_dir/src/profiledata.h",
"$tcmalloc_dir/src/profile-handler.cc",
"$tcmalloc_dir/src/profile-handler.h",
+ "$tcmalloc_dir/src/profiledata.cc",
+ "$tcmalloc_dir/src/profiledata.h",
"$tcmalloc_dir/src/profiler.cc",
]
defines += [ "PERFTOOLS_DLL_DECL=" ]
diff --git a/allocator/allocator.gyp b/allocator/allocator.gyp
index c20325d..d426c9c 100644
--- a/allocator/allocator.gyp
+++ b/allocator/allocator.gyp
@@ -106,9 +106,9 @@
'<(tcmalloc_dir)/src/base/abort.cc',
'<(tcmalloc_dir)/src/base/abort.h',
'<(tcmalloc_dir)/src/base/arm_instruction_set_select.h',
- '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-arm-generic.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-arm-v6plus.h',
+ '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-macosx.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-windows.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-x86.cc',
@@ -322,10 +322,10 @@
# cpuprofiler
'<(tcmalloc_dir)/src/base/thread_lister.c',
'<(tcmalloc_dir)/src/base/thread_lister.h',
- '<(tcmalloc_dir)/src/profiledata.cc',
- '<(tcmalloc_dir)/src/profiledata.h',
'<(tcmalloc_dir)/src/profile-handler.cc',
'<(tcmalloc_dir)/src/profile-handler.h',
+ '<(tcmalloc_dir)/src/profiledata.cc',
+ '<(tcmalloc_dir)/src/profiledata.h',
'<(tcmalloc_dir)/src/profiler.cc',
],
}],
@@ -434,9 +434,9 @@
'../..',
],
'sources': [
- 'allocator_unittest.cc',
'../profiler/alternate_timer.cc',
'../profiler/alternate_timer.h',
+ 'allocator_unittest.cc',
],
},
],
@@ -499,10 +499,10 @@
'../..',
],
'sources': [
- 'type_profiler_tcmalloc.cc',
- 'type_profiler_tcmalloc.h',
'<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
'<(tcmalloc_dir)/src/type_profiler_map.cc',
+ 'type_profiler_tcmalloc.cc',
+ 'type_profiler_tcmalloc.h',
],
},
{
@@ -542,9 +542,9 @@
'../..',
],
'sources': [
- 'type_profiler_map_unittest.cc',
'<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
'<(tcmalloc_dir)/src/type_profiler_map.cc',
+ 'type_profiler_map_unittest.cc',
],
},
],
diff --git a/allocator/allocator_unittest.cc b/allocator/allocator_unittest.cc
index 9471e95..a1d1ef0 100644
--- a/allocator/allocator_unittest.cc
+++ b/allocator/allocator_unittest.cc
@@ -6,7 +6,7 @@
#include <stdlib.h>
#include <algorithm> // for min()
-#include "base/atomicops.h"
+#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
// Number of bits in a size_t.
@@ -15,10 +15,6 @@
static const size_t kMaxSize = ~static_cast<size_t>(0);
// Maximum positive size of a size_t if it were signed.
static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1);
-// An allocation size which is not too big to be reasonable.
-static const size_t kNotTooBig = 100000;
-// An allocation size which is just too big.
-static const size_t kTooBig = ~static_cast<size_t>(0);
namespace {
@@ -82,197 +78,6 @@
}
}
-template <class AtomicType>
-static void TestAtomicIncrement() {
- // For now, we just test single threaded execution
-
- // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
- // outside the expected address bounds. This is in particular to
- // test that some future change to the asm code doesn't cause the
- // 32-bit NoBarrier_AtomicIncrement to do the wrong thing on 64-bit machines.
- struct {
- AtomicType prev_word;
- AtomicType count;
- AtomicType next_word;
- } s;
-
- AtomicType prev_word_value, next_word_value;
- memset(&prev_word_value, 0xFF, sizeof(AtomicType));
- memset(&next_word_value, 0xEE, sizeof(AtomicType));
-
- s.prev_word = prev_word_value;
- s.count = 0;
- s.next_word = next_word_value;
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
- EXPECT_EQ(s.count, 1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
- EXPECT_EQ(s.count, 3);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
- EXPECT_EQ(s.count, 6);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
- EXPECT_EQ(s.count, 3);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
- EXPECT_EQ(s.count, 1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
- EXPECT_EQ(s.count, 0);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
- EXPECT_EQ(s.count, -1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
- EXPECT_EQ(s.count, -5);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
- EXPECT_EQ(s.count, 0);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-}
-
-
-#define NUM_BITS(T) (sizeof(T) * 8)
-
-
-template <class AtomicType>
-static void TestCompareAndSwap() {
- AtomicType value = 0;
- AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
- EXPECT_EQ(1, value);
- EXPECT_EQ(0, prev);
-
- // Use test value that has non-zero bits in both halves, more for testing
- // 64-bit implementation on 32-bit platforms.
- const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
- (NUM_BITS(AtomicType) - 2)) + 11;
- value = k_test_val;
- prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
- EXPECT_EQ(k_test_val, value);
- EXPECT_EQ(k_test_val, prev);
-
- value = k_test_val;
- prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
- EXPECT_EQ(5, value);
- EXPECT_EQ(k_test_val, prev);
-}
-
-
-template <class AtomicType>
-static void TestAtomicExchange() {
- AtomicType value = 0;
- AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
- EXPECT_EQ(1, value);
- EXPECT_EQ(0, new_value);
-
- // Use test value that has non-zero bits in both halves, more for testing
- // 64-bit implementation on 32-bit platforms.
- const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
- (NUM_BITS(AtomicType) - 2)) + 11;
- value = k_test_val;
- new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
- EXPECT_EQ(k_test_val, value);
- EXPECT_EQ(k_test_val, new_value);
-
- value = k_test_val;
- new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
- EXPECT_EQ(5, value);
- EXPECT_EQ(k_test_val, new_value);
-}
-
-
-template <class AtomicType>
-static void TestAtomicIncrementBounds() {
- // Test increment at the half-width boundary of the atomic type.
- // It is primarily for testing at the 32-bit boundary for 64-bit atomic type.
- AtomicType test_val = static_cast<uint64_t>(1) << (NUM_BITS(AtomicType) / 2);
- AtomicType value = test_val - 1;
- AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
- EXPECT_EQ(test_val, value);
- EXPECT_EQ(value, new_value);
-
- base::subtle::NoBarrier_AtomicIncrement(&value, -1);
- EXPECT_EQ(test_val - 1, value);
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestStore() {
- const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
- const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
- AtomicType value;
-
- base::subtle::NoBarrier_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::NoBarrier_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-
- base::subtle::Acquire_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::Acquire_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-
- base::subtle::Release_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::Release_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestLoad() {
- const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
- const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
- AtomicType value;
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
-}
-
-template <class AtomicType>
-static void TestAtomicOps() {
- TestCompareAndSwap<AtomicType>();
- TestAtomicExchange<AtomicType>();
- TestAtomicIncrementBounds<AtomicType>();
- TestStore<AtomicType>();
- TestLoad<AtomicType>();
-}
-
static void TestCalloc(size_t n, size_t s, bool ok) {
char* p = reinterpret_cast<char*>(calloc(n, s));
if (!ok) {
@@ -287,80 +92,10 @@
}
}
-// MSVC C4530 complains about exception handler usage when exceptions are
-// disabled. Temporarily disable that warning so we can test that they are, in
-// fact, disabled.
-#if defined(OS_WIN)
-#pragma warning(push)
-#pragma warning(disable: 4530)
-#endif
-
-// A global test counter for number of times the NewHandler is called.
-static int news_handled = 0;
-static void TestNewHandler() {
- ++news_handled;
- throw std::bad_alloc();
-}
-
-// Because we compile without exceptions, we expect these will not throw.
-static void TestOneNewWithoutExceptions(void* (*func)(size_t),
- bool should_throw) {
- // success test
- try {
- void* ptr = (*func)(kNotTooBig);
- EXPECT_NE(reinterpret_cast<void*>(NULL), ptr) <<
- "allocation should not have failed.";
- } catch(...) {
- EXPECT_EQ(0, 1) << "allocation threw unexpected exception.";
- }
-
- // failure test
- try {
- void* rv = (*func)(kTooBig);
- EXPECT_EQ(NULL, rv);
- EXPECT_FALSE(should_throw) << "allocation should have thrown.";
- } catch(...) {
- EXPECT_TRUE(should_throw) << "allocation threw unexpected exception.";
- }
-}
-
-static void TestNothrowNew(void* (*func)(size_t)) {
- news_handled = 0;
-
- // test without new_handler:
- std::new_handler saved_handler = std::set_new_handler(0);
- TestOneNewWithoutExceptions(func, false);
-
- // test with new_handler:
- std::set_new_handler(TestNewHandler);
- TestOneNewWithoutExceptions(func, true);
- EXPECT_EQ(news_handled, 1) << "nothrow new_handler was not called.";
- std::set_new_handler(saved_handler);
-}
-
-#if defined(OS_WIN)
-#pragma warning(pop)
-#endif
-
} // namespace
//-----------------------------------------------------------------------------
-TEST(Atomics, AtomicIncrementWord) {
- TestAtomicIncrement<base::subtle::AtomicWord>();
-}
-
-TEST(Atomics, AtomicIncrement32) {
- TestAtomicIncrement<base::subtle::Atomic32>();
-}
-
-TEST(Atomics, AtomicOpsWord) {
- TestAtomicIncrement<base::subtle::AtomicWord>();
-}
-
-TEST(Atomics, AtomicOps32) {
- TestAtomicIncrement<base::subtle::Atomic32>();
-}
TEST(Allocators, Malloc) {
// Try allocating data with a bunch of alignments and sizes
@@ -394,11 +129,6 @@
TestCalloc(kMaxSignedSize, kMaxSignedSize, false);
}
-TEST(Allocators, New) {
- TestNothrowNew(&::operator new);
- TestNothrowNew(&::operator new[]);
-}
-
// This makes sure that reallocing a small number of bytes in either
// direction doesn't cause us to allocate new memory.
TEST(Allocators, Realloc1) {
@@ -458,23 +188,6 @@
free(p);
}
-// tcmalloc uses these semantics but system allocators can return NULL for
-// realloc(ptr, 0).
-#if defined(USE_TCMALLOC)
-TEST(Allocators, ReallocZero) {
- // Test that realloc to zero does not return NULL.
- for (int size = 0; size >= 0; size = NextSize(size)) {
- char* ptr = reinterpret_cast<char*>(malloc(size));
- EXPECT_NE(static_cast<char*>(NULL), ptr);
- ptr = reinterpret_cast<char*>(realloc(ptr, 0));
- EXPECT_NE(static_cast<char*>(NULL), ptr);
- if (ptr)
- free(ptr);
- }
-}
-#endif
-
-#ifdef WIN32
// Test recalloc
TEST(Allocators, Recalloc) {
for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
@@ -499,7 +212,7 @@
// Try allocating data with a bunch of alignments and sizes
static const int kTestAlignments[] = {8, 16, 256, 4096, 8192, 16384};
for (int size = 1; size > 0; size = NextSize(size)) {
- for (int i = 0; i < ARRAYSIZE(kTestAlignments); ++i) {
+ for (int i = 0; i < arraysize(kTestAlignments); ++i) {
unsigned char* ptr = static_cast<unsigned char*>(
_aligned_malloc(size, kTestAlignments[i]));
CheckAlignment(ptr, kTestAlignments[i]);
@@ -526,9 +239,6 @@
}
}
-#endif
-
-
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/android/application_status_listener.cc b/android/application_status_listener.cc
index f487072..02178c4 100644
--- a/android/application_status_listener.cc
+++ b/android/application_status_listener.cc
@@ -60,7 +60,8 @@
// static
void ApplicationStatusListener::NotifyApplicationStateChange(
ApplicationState state) {
- g_observers.Get().Notify(&ApplicationStatusListener::Notify, state);
+ g_observers.Get().Notify(FROM_HERE, &ApplicationStatusListener::Notify,
+ state);
}
static void OnApplicationStateChange(JNIEnv* env,
diff --git a/android/build_info.h b/android/build_info.h
index cef8145..e4e84e8 100644
--- a/android/build_info.h
+++ b/android/build_info.h
@@ -15,6 +15,19 @@
namespace base {
namespace android {
+// This enumeration maps to the values returned by BuildInfo::sdk_int(),
+// indicating the Android release associated with a given SDK version.
+enum SdkVersion {
+ SDK_VERSION_ICE_CREAM_SANDWICH = 14,
+ SDK_VERSION_ICE_CREAM_SANDWICH_MR1 = 15,
+ SDK_VERSION_JELLY_BEAN = 16,
+ SDK_VERSION_JELLY_BEAN_MR1 = 17,
+ SDK_VERSION_JELLY_BEAN_MR2 = 18,
+ SDK_VERSION_KITKAT = 19,
+ SDK_VERSION_KITKAT_WEAR = 20,
+ SDK_VERSION_LOLLIPOP = 21
+};
+
// BuildInfo is a singleton class that stores android build and device
// information. It will be called from Android specific code and gets used
// primarily in crash reporting.
diff --git a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 2168c21..d68fb4a 100644
--- a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -8,6 +8,7 @@
import android.os.SystemClock;
import android.util.Log;
+import org.chromium.base.CalledByNative;
import org.chromium.base.CommandLine;
import org.chromium.base.JNINamespace;
import org.chromium.base.TraceEvent;
@@ -40,41 +41,68 @@
// Guards all access to the libraries
private static final Object sLock = new Object();
+ // The singleton instance of LibraryLoader.
+ private static LibraryLoader sInstance;
+
// One-way switch becomes true when the libraries are loaded.
- private static boolean sLoaded = false;
+ private boolean mLoaded;
// One-way switch becomes true when the Java command line is switched to
// native.
- private static boolean sCommandLineSwitched = false;
+ private boolean mCommandLineSwitched;
// One-way switch becomes true when the libraries are initialized (
// by calling nativeLibraryLoaded, which forwards to LibraryLoaded(...) in
// library_loader_hooks.cc).
- private static boolean sInitialized = false;
+ private boolean mInitialized;
// One-way switches recording attempts to use Relro sharing in the browser.
// The flags are used to report UMA stats later.
- private static boolean sIsUsingBrowserSharedRelros = false;
- private static boolean sLoadAtFixedAddressFailed = false;
+ private boolean mIsUsingBrowserSharedRelros;
+ private boolean mLoadAtFixedAddressFailed;
// One-way switch becomes true if the device supports memory mapping the
// APK file with executable permissions.
- private static boolean sMapApkWithExecPermission = false;
+ private boolean mMapApkWithExecPermission;
// One-way switch to indicate whether we probe for memory mapping the APK
// file with executable permissions. We suppress the probe under some
// conditions.
// For more, see:
// https://code.google.com/p/chromium/issues/detail?id=448084
- private static boolean sProbeMapApkWithExecPermission = true;
+ private boolean mProbeMapApkWithExecPermission = true;
// One-way switch becomes true if the Chromium library was loaded from the
// APK file directly.
- private static boolean sLibraryWasLoadedFromApk = false;
+ private boolean mLibraryWasLoadedFromApk;
// One-way switch becomes false if the Chromium library should be loaded
// directly from the APK file but it was compressed or not aligned.
- private static boolean sLibraryIsMappableInApk = true;
+ private boolean mLibraryIsMappableInApk = true;
+
+ // The type of process the shared library is loaded in.
+ private int mLibraryProcessType;
+
+ /**
+ * @param libraryProcessType the process the shared library is loaded in. refer to
+ * LibraryProcessType for possible values.
+ * @return LibraryLoader if existing, otherwise create a new one.
+ */
+ public static LibraryLoader get(int libraryProcessType) throws ProcessInitException {
+ synchronized (sLock) {
+ if (sInstance != null) {
+ if (sInstance.mLibraryProcessType == libraryProcessType) return sInstance;
+ throw new ProcessInitException(
+ LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED);
+ }
+ sInstance = new LibraryLoader(libraryProcessType);
+ return sInstance;
+ }
+ }
+
+ private LibraryLoader(int libraryProcessType) {
+ mLibraryProcessType = libraryProcessType;
+ }
/**
* The same as ensureInitialized(null, false), should only be called
@@ -82,7 +110,7 @@
*
* @throws ProcessInitException
*/
- public static void ensureInitialized() throws ProcessInitException {
+ public void ensureInitialized() throws ProcessInitException {
ensureInitialized(null, false);
}
@@ -96,11 +124,11 @@
* @param shouldDeleteFallbackLibraries The flag tells whether the method
* should delete the fallback libraries or not.
*/
- public static void ensureInitialized(
+ public void ensureInitialized(
Context context, boolean shouldDeleteFallbackLibraries)
throws ProcessInitException {
synchronized (sLock) {
- if (sInitialized) {
+ if (mInitialized) {
// Already initialized, nothing to do.
return;
}
@@ -114,7 +142,7 @@
*/
public static boolean isInitialized() {
synchronized (sLock) {
- return sInitialized;
+ return sInstance != null && sInstance.mInitialized;
}
}
@@ -124,7 +152,7 @@
*
* @throws ProcessInitException
*/
- public static void loadNow() throws ProcessInitException {
+ public void loadNow() throws ProcessInitException {
loadNow(null, false);
}
@@ -141,7 +169,7 @@
*
* @throws ProcessInitException if the native library failed to load.
*/
- public static void loadNow(Context context, boolean shouldDeleteFallbackLibraries)
+ public void loadNow(Context context, boolean shouldDeleteFallbackLibraries)
throws ProcessInitException {
synchronized (sLock) {
loadAlreadyLocked(context, shouldDeleteFallbackLibraries);
@@ -153,19 +181,19 @@
* native will call its "main" thread. The library must have previously been
* loaded with loadNow.
*/
- public static void initialize() throws ProcessInitException {
+ public void initialize() throws ProcessInitException {
synchronized (sLock) {
initializeAlreadyLocked();
}
}
// Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code
- private static void loadAlreadyLocked(
+ private void loadAlreadyLocked(
Context context, boolean shouldDeleteFallbackLibraries)
throws ProcessInitException {
try {
- if (!sLoaded) {
- assert !sInitialized;
+ if (!mLoaded) {
+ assert !mInitialized;
long startTime = SystemClock.uptimeMillis();
boolean useChromiumLinker = Linker.isUsed();
@@ -183,17 +211,17 @@
if (manufacturer != null
&& manufacturer.toLowerCase(Locale.ENGLISH).contains("samsung")) {
Log.w(TAG, "Suppressed load from APK support check on this device");
- sProbeMapApkWithExecPermission = false;
+ mProbeMapApkWithExecPermission = false;
}
// Check if the device supports memory mapping the APK file
// with executable permissions.
if (context != null) {
apkFilePath = context.getApplicationInfo().sourceDir;
- if (sProbeMapApkWithExecPermission) {
- sMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
+ if (mProbeMapApkWithExecPermission) {
+ mMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
}
- if (!sMapApkWithExecPermission && Linker.isInZipFile()) {
+ if (!mMapApkWithExecPermission && Linker.isInZipFile()) {
Log.w(TAG, "the no map executable support fallback will be used because"
+ " memory mapping the APK file with executable permissions is"
+ " not supported");
@@ -222,9 +250,9 @@
if (apkFilePath != null && Linker.isInZipFile()) {
// The library is in the APK file.
if (!Linker.checkLibraryIsMappableInApk(apkFilePath, libFilePath)) {
- sLibraryIsMappableInApk = false;
+ mLibraryIsMappableInApk = false;
}
- if (sLibraryIsMappableInApk || useMapExecSupportFallback) {
+ if (mLibraryIsMappableInApk || useMapExecSupportFallback) {
// Load directly from the APK (or use the no map executable
// support fallback, see crazy_linker_elf_loader.cpp).
zipFilePath = apkFilePath;
@@ -251,7 +279,7 @@
// Load the library.
boolean isLoaded = false;
if (Linker.isUsingBrowserSharedRelros()) {
- sIsUsingBrowserSharedRelros = true;
+ mIsUsingBrowserSharedRelros = true;
try {
loadLibrary(zipFilePath, libFilePath);
isLoaded = true;
@@ -259,7 +287,7 @@
Log.w(TAG, "Failed to load native library with shared RELRO, "
+ "retrying without");
Linker.disableSharedRelros();
- sLoadAtFixedAddressFailed = true;
+ mLoadAtFixedAddressFailed = true;
}
}
if (!isLoaded) {
@@ -287,7 +315,7 @@
startTime % 10000,
stopTime % 10000));
- sLoaded = true;
+ mLoaded = true;
}
} catch (UnsatisfiedLinkError e) {
throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED, e);
@@ -305,17 +333,17 @@
// Load a native shared library with the Chromium linker. If the zip file
// path is not null, the library is loaded directly from the zip file.
- private static void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
+ private void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
Linker.loadLibrary(zipFilePath, libFilePath);
if (zipFilePath != null) {
- sLibraryWasLoadedFromApk = true;
+ mLibraryWasLoadedFromApk = true;
}
}
// The WebView requires the Command Line to be switched over before
// initialization is done. This is okay in the WebView's case since the
// JNI is already loaded by this point.
- public static void switchCommandLineForWebView() {
+ public void switchCommandLineForWebView() {
synchronized (sLock) {
ensureCommandLineSwitchedAlreadyLocked();
}
@@ -324,24 +352,24 @@
// Switch the CommandLine over from Java to native if it hasn't already been done.
// This must happen after the code is loaded and after JNI is ready (since after the
// switch the Java CommandLine will delegate all calls the native CommandLine).
- private static void ensureCommandLineSwitchedAlreadyLocked() {
- assert sLoaded;
- if (sCommandLineSwitched) {
+ private void ensureCommandLineSwitchedAlreadyLocked() {
+ assert mLoaded;
+ if (mCommandLineSwitched) {
return;
}
nativeInitCommandLine(CommandLine.getJavaSwitchesOrNull());
CommandLine.enableNativeProxy();
- sCommandLineSwitched = true;
+ mCommandLineSwitched = true;
}
// Invoke base::android::LibraryLoaded in library_loader_hooks.cc
- private static void initializeAlreadyLocked() throws ProcessInitException {
- if (sInitialized) {
+ private void initializeAlreadyLocked() throws ProcessInitException {
+ if (mInitialized) {
return;
}
// Setup the native command line if necessary.
- if (!sCommandLineSwitched) {
+ if (!mCommandLineSwitched) {
nativeInitCommandLine(CommandLine.getJavaSwitchesOrNull());
}
@@ -352,13 +380,13 @@
// From this point on, native code is ready to use and checkIsReady()
// shouldn't complain from now on (and in fact, it's used by the
// following calls).
- sInitialized = true;
+ mInitialized = true;
// The Chrome JNI is registered by now so we can switch the Java
// command line over to delegating to native if it's necessary.
- if (!sCommandLineSwitched) {
+ if (!mCommandLineSwitched) {
CommandLine.enableNativeProxy();
- sCommandLineSwitched = true;
+ mCommandLineSwitched = true;
}
// From now on, keep tracing in sync with native.
@@ -366,32 +394,32 @@
}
// Called after all native initializations are complete.
- public static void onNativeInitializationComplete(Context context) {
+ public void onNativeInitializationComplete(Context context) {
recordBrowserProcessHistogram(context);
}
// Record Chromium linker histogram state for the main browser process. Called from
// onNativeInitializationComplete().
- private static void recordBrowserProcessHistogram(Context context) {
+ private void recordBrowserProcessHistogram(Context context) {
if (Linker.isUsed()) {
- nativeRecordChromiumAndroidLinkerBrowserHistogram(sIsUsingBrowserSharedRelros,
- sLoadAtFixedAddressFailed,
+ nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSharedRelros,
+ mLoadAtFixedAddressFailed,
getLibraryLoadFromApkStatus(context));
}
}
// Returns the device's status for loading a library directly from the APK file.
// This method can only be called when the Chromium linker is used.
- private static int getLibraryLoadFromApkStatus(Context context) {
+ private int getLibraryLoadFromApkStatus(Context context) {
assert Linker.isUsed();
- if (sLibraryWasLoadedFromApk) {
- return sMapApkWithExecPermission
+ if (mLibraryWasLoadedFromApk) {
+ return mMapApkWithExecPermission
? LibraryLoadFromApkStatusCodes.SUCCESSFUL
: LibraryLoadFromApkStatusCodes.USED_NO_MAP_EXEC_SUPPORT_FALLBACK;
}
- if (!sLibraryIsMappableInApk) {
+ if (!mLibraryIsMappableInApk) {
return LibraryLoadFromApkStatusCodes.USED_UNPACK_LIBRARY_FALLBACK;
}
@@ -400,11 +428,11 @@
return LibraryLoadFromApkStatusCodes.UNKNOWN;
}
- if (!sProbeMapApkWithExecPermission) {
+ if (!mProbeMapApkWithExecPermission) {
return LibraryLoadFromApkStatusCodes.UNKNOWN;
}
- return sMapApkWithExecPermission
+ return mMapApkWithExecPermission
? LibraryLoadFromApkStatusCodes.SUPPORTED
: LibraryLoadFromApkStatusCodes.NOT_SUPPORTED;
}
@@ -413,15 +441,27 @@
// recorded as a histogram immediately because histograms and IPC are not ready at the
// time it are captured. This function stores a pending value, so that a later call to
// RecordChromiumAndroidLinkerRendererHistogram() will record it correctly.
- public static void registerRendererProcessHistogram(boolean requestedSharedRelro,
- boolean loadAtFixedAddressFailed) {
+ public void registerRendererProcessHistogram(boolean requestedSharedRelro,
+ boolean loadAtFixedAddressFailed) {
if (Linker.isUsed()) {
nativeRegisterChromiumAndroidLinkerRendererHistogram(requestedSharedRelro,
loadAtFixedAddressFailed);
}
}
- private static native void nativeInitCommandLine(String[] initCommandLine);
+ /**
+ * @return the process the shared library is loaded in, see the LibraryProcessType
+ * for possible values.
+ */
+ @CalledByNative
+ public static int getLibraryProcessType() {
+ synchronized (sLock) {
+ if (sInstance == null) return LibraryProcessType.PROCESS_UNINITIALIZED;
+ return sInstance.mLibraryProcessType;
+ }
+ }
+
+ private native void nativeInitCommandLine(String[] initCommandLine);
// Only methods needed before or during normal JNI registration are during System.OnLoad.
// nativeLibraryLoaded is then called to register everything else. This process is called
@@ -429,13 +469,13 @@
// definition in base/android/library_loader/library_loader_hooks.cc.
//
// Return true on success and false on failure.
- private static native boolean nativeLibraryLoaded();
+ private native boolean nativeLibraryLoaded();
// Method called to record statistics about the Chromium linker operation for the main
// browser process. Indicates whether the linker attempted relro sharing for the browser,
// and if it did, whether the library failed to load at a fixed address. Also records
// support for loading a library directly from the APK file.
- private static native void nativeRecordChromiumAndroidLinkerBrowserHistogram(
+ private native void nativeRecordChromiumAndroidLinkerBrowserHistogram(
boolean isUsingBrowserSharedRelros,
boolean loadAtFixedAddressFailed,
int libraryLoadFromApkStatus);
@@ -443,11 +483,11 @@
// Method called to register (for later recording) statistics about the Chromium linker
// operation for a renderer process. Indicates whether the linker attempted relro sharing,
// and if it did, whether the library failed to load at a fixed address.
- private static native void nativeRegisterChromiumAndroidLinkerRendererHistogram(
+ private native void nativeRegisterChromiumAndroidLinkerRendererHistogram(
boolean requestedSharedRelro,
boolean loadAtFixedAddressFailed);
// Get the version of the native library. This is needed so that we can check we
// have the right version before initializing the (rest of the) JNI.
- private static native String nativeGetVersionNumber();
+ private native String nativeGetVersionNumber();
}
diff --git a/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/android/java/src/org/chromium/base/metrics/RecordHistogram.java
index 050708c..08c314f 100644
--- a/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ b/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -7,16 +7,21 @@
import org.chromium.base.JNINamespace;
import org.chromium.base.VisibleForTesting;
+import java.util.concurrent.TimeUnit;
+
/**
- * Java API for recording UMA histograms. As opposed to macros used in native code, these calls are
- * not caching the histogram pointer; also, the JNI calls are relatively costly - avoid calling
- * these methods in performance-critical code.
+ * Java API for recording UMA histograms. Internally, the histogram will be cached by
+ * System.identityHashCode(name).
+ *
+ * Note: the JNI calls are relatively costly - avoid calling these methods in performance-critical
+ * code.
*/
@JNINamespace("base::android")
public class RecordHistogram {
/**
* Records a sample in a boolean UMA histogram of the given name. Boolean histogram has two
- * buckets, corresponding to success (true) and failure (false).
+ * buckets, corresponding to success (true) and failure (false). This is the Java equivalent of
+ * the UMA_HISTOGRAM_BOOLEAN C++ macro.
* @param name name of the histogram
* @param sample sample to be recorded, either true or false
*/
@@ -26,7 +31,8 @@
/**
* Records a sample in an enumerated histogram of the given name and boundary. Note that
- * |boundary| identifies the histogram - it should be the same at every invocation.
+ * |boundary| identifies the histogram - it should be the same at every invocation. This is the
+ * Java equivalent of the UMA_HISTOGRAM_ENUMERATION C++ macro.
* @param name name of the histogram
* @param sample sample to be recorded, at least 0 and at most |boundary| - 1
* @param boundary upper bound for legal sample values - all sample values has to be strictly
@@ -37,6 +43,64 @@
}
/**
+ * Records a sample in a histogram of times. Useful for recording short durations. This is the
+ * Java equivalent of the UMA_HISTOGRAM_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param timeUnit the unit of the duration argument
+ */
+ public static void recordTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+ recordCustomTimesHistogramMilliseconds(
+ name, timeUnit.toMillis(duration), 1, TimeUnit.SECONDS.toMillis(10), 50);
+ }
+
+ /**
+ * Records a sample in a histogram of times. Useful for recording medium durations. This is the
+ * Java equivalent of the UMA_HISTOGRAM_MEDIUM_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param timeUnit the unit of the duration argument
+ */
+ public static void recordMediumTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+ recordCustomTimesHistogramMilliseconds(
+ name, timeUnit.toMillis(duration), 10, TimeUnit.MINUTES.toMillis(3), 50);
+ }
+
+ /**
+ * Records a sample in a histogram of times. Useful for recording long durations. This is the
+ * Java equivalent of the UMA_HISTOGRAM_LONG_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param timeUnit the unit of the duration argument
+ */
+ public static void recordLongTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+ recordCustomTimesHistogramMilliseconds(
+ name, timeUnit.toMillis(duration), 1, TimeUnit.HOURS.toMillis(1), 50);
+ }
+
+ /**
+ * Records a sample in a histogram of times with custom buckets. This is the Java equivalent of
+ * the UMA_HISTOGRAM_CUSTOM_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param min the minimum bucket value
+ * @param max the maximum bucket value
+ * @param timeUnit the unit of the duration, min, and max arguments
+ * @param numBuckets the number of buckets
+ */
+ public static void recordCustomTimesHistogram(
+ String name, long duration, long min, long max, TimeUnit timeUnit, int numBuckets) {
+ recordCustomTimesHistogramMilliseconds(name, timeUnit.toMillis(duration),
+ timeUnit.toMillis(min), timeUnit.toMillis(max), numBuckets);
+ }
+
+ private static void recordCustomTimesHistogramMilliseconds(
+ String name, long duration, long min, long max, int numBuckets) {
+ nativeRecordCustomTimesHistogramMilliseconds(
+ name, System.identityHashCode(name), duration, min, max, numBuckets);
+ }
+
+ /**
* Returns the number of samples recorded in the given bucket of the given histogram.
* @param name name of the histogram to look up
* @param sample the bucket containing this sample value will be looked up
@@ -53,6 +117,9 @@
nativeInitialize();
}
+ private static native void nativeRecordCustomTimesHistogramMilliseconds(
+ String name, int key, long duration, long min, long max, int numBuckets);
+
private static native void nativeRecordBooleanHistogram(String name, int key, boolean sample);
private static native void nativeRecordEnumeratedHistogram(
String name, int key, int sample, int boundary);
diff --git a/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java b/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
index 82c1ca9..f0489d3 100644
--- a/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
+++ b/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
@@ -8,8 +8,11 @@
import android.test.suitebuilder.annotation.SmallTest;
import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
+import java.util.concurrent.TimeUnit;
+
/**
* Tests for the Java API for recording UMA histograms.
*/
@@ -17,7 +20,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- LibraryLoader.ensureInitialized();
+ LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
RecordHistogram.initialize();
}
@@ -75,4 +78,41 @@
assertEquals(0, oneCount.getDelta());
assertEquals(1, twoCount.getDelta());
}
+
+ /**
+ * Tests recording of custom times histograms.
+ */
+ @SmallTest
+ public void testRecordCustomTimesHistogram() {
+ String histogram = "HelloWorld.CustomTimesMetric";
+ HistogramDelta zeroCount = new HistogramDelta(histogram, 0);
+ HistogramDelta oneCount = new HistogramDelta(histogram, 1);
+ HistogramDelta twoCount = new HistogramDelta(histogram, 100);
+
+ assertEquals(0, zeroCount.getDelta());
+ assertEquals(0, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ TimeUnit milli = TimeUnit.MILLISECONDS;
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
+ assertEquals(1, zeroCount.getDelta());
+ assertEquals(0, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
+ assertEquals(2, zeroCount.getDelta());
+ assertEquals(0, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 95, 1, 100, milli, 3);
+ assertEquals(2, zeroCount.getDelta());
+ assertEquals(1, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 200, 1, 100, milli, 3);
+ assertEquals(2, zeroCount.getDelta());
+ assertEquals(1, oneCount.getDelta());
+ assertEquals(1, twoCount.getDelta());
+ }
}
diff --git a/android/jni_array.cc b/android/jni_array.cc
index 4bebec7..a157354 100644
--- a/android/jni_array.cc
+++ b/android/jni_array.cc
@@ -7,7 +7,6 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
-#include "base/stl_util.h"
namespace base {
namespace android {
@@ -54,7 +53,7 @@
ScopedJavaLocalRef<jintArray> ToJavaIntArray(
JNIEnv* env, const std::vector<int>& ints) {
- return ToJavaIntArray(env, vector_as_array(&ints), ints.size());
+ return ToJavaIntArray(env, ints.begin(), ints.size());
}
ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
@@ -73,7 +72,7 @@
// Returns a new Java long array converted from the given int64 array.
BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
JNIEnv* env, const std::vector<int64>& longs) {
- return ToJavaLongArray(env, vector_as_array(&longs), longs.size());
+ return ToJavaLongArray(env, longs.begin(), longs.size());
}
ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
diff --git a/android/jni_generator/jni_generator.py b/android/jni_generator/jni_generator.py
index 53de365..6e39c13 100755
--- a/android/jni_generator/jni_generator.py
+++ b/android/jni_generator/jni_generator.py
@@ -209,7 +209,11 @@
@staticmethod
def ParseJavaPSignature(signature_line):
prefix = 'Signature: '
- return '"%s"' % signature_line[signature_line.index(prefix) + len(prefix):]
+ index = signature_line.find(prefix)
+ if index == -1:
+ prefix = 'descriptor: '
+ index = signature_line.index(prefix)
+ return '"%s"' % signature_line[index + len(prefix):]
@staticmethod
def JavaToJni(param):
diff --git a/android/jni_generator/jni_generator_tests.py b/android/jni_generator/jni_generator_tests.py
index a7ce537..7e39cda 100755
--- a/android/jni_generator/jni_generator_tests.py
+++ b/android/jni_generator/jni_generator_tests.py
@@ -722,7 +722,7 @@
self.assertEquals(1, len(jni_from_javap.called_by_natives))
self.assertGoldenTextEquals(jni_from_javap.GetContent())
- def testSnippnetJavap6_7(self):
+ def testSnippnetJavap6_7_8(self):
content_javap6 = """
public class java.util.HashSet {
public boolean add(java.lang.Object);
@@ -736,16 +736,30 @@
Signature: (Ljava/lang/Object;)Z
}
"""
+
+ content_javap8 = """
+public class java.util.HashSet {
+ public boolean add(E);
+ descriptor: (Ljava/lang/Object;)Z
+}
+"""
+
jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
TestOptions())
jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
TestOptions())
+ jni_from_javap8 = jni_generator.JNIFromJavaP(content_javap8.split('\n'),
+ TestOptions())
self.assertTrue(jni_from_javap6.GetContent())
self.assertTrue(jni_from_javap7.GetContent())
+ self.assertTrue(jni_from_javap8.GetContent())
# Ensure the javap7 is correctly parsed and uses the Signature field rather
# than the "E" parameter.
self.assertTextEquals(jni_from_javap6.GetContent(),
jni_from_javap7.GetContent())
+ # Ensure the javap8 is correctly parsed and uses the descriptor field.
+ self.assertTextEquals(jni_from_javap7.GetContent(),
+ jni_from_javap8.GetContent())
def testFromJavaP(self):
contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]),
diff --git a/android/library_loader/library_loader_hooks.cc b/android/library_loader/library_loader_hooks.cc
index 965d030..97aec8c 100644
--- a/android/library_loader/library_loader_hooks.cc
+++ b/android/library_loader/library_loader_hooks.cc
@@ -51,7 +51,7 @@
static void RegisterChromiumAndroidLinkerRendererHistogram(
JNIEnv* env,
- jclass clazz,
+ jobject jcaller,
jboolean requested_shared_relro,
jboolean load_at_fixed_address_failed) {
// Note a pending histogram value for later recording.
@@ -75,7 +75,7 @@
static void RecordChromiumAndroidLinkerBrowserHistogram(
JNIEnv* env,
- jclass clazz,
+ jobject jcaller,
jboolean is_using_browser_shared_relros,
jboolean load_at_fixed_address_failed,
jint library_load_from_apk_status) {
@@ -102,16 +102,17 @@
g_registration_callback = func;
}
-static void InitCommandLine(JNIEnv* env, jclass clazz,
+static void InitCommandLine(JNIEnv* env,
+ jobject jcaller,
jobjectArray init_command_line) {
InitNativeCommandLineFromJavaArray(env, init_command_line);
}
-static jboolean LibraryLoaded(JNIEnv* env, jclass clazz) {
+static jboolean LibraryLoaded(JNIEnv* env, jobject jcaller) {
if (g_registration_callback == NULL) {
return true;
}
- return g_registration_callback(env, clazz);
+ return g_registration_callback(env, NULL);
}
void LibraryLoaderExitHook() {
@@ -132,9 +133,14 @@
g_library_version_number = strdup(version_number);
}
-jstring GetVersionNumber(JNIEnv* env, jclass clazz) {
+jstring GetVersionNumber(JNIEnv* env, jobject jcaller) {
return ConvertUTF8ToJavaString(env, g_library_version_number).Release();
}
+LibraryProcessType GetLibraryProcessType(JNIEnv* env) {
+ return static_cast<LibraryProcessType>(
+ Java_LibraryLoader_getLibraryProcessType(env));
+}
+
} // namespace android
} // namespace base
diff --git a/android/library_loader/library_loader_hooks.h b/android/library_loader/library_loader_hooks.h
index 78dc535..6203eb0 100644
--- a/android/library_loader/library_loader_hooks.h
+++ b/android/library_loader/library_loader_hooks.h
@@ -12,6 +12,19 @@
namespace base {
namespace android {
+// The process the shared library is loaded in.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.library_loader
+enum LibraryProcessType {
+ // The LibraryLoad has not been initialized.
+ PROCESS_UNINITIALIZED = 0,
+ // Shared library is running in browser process.
+ PROCESS_BROWSER = 1,
+ // Shared library is running in child process.
+ PROCESS_CHILD = 2,
+ // Shared library is running in webview process.
+ PROCESS_WEBVIEW = 3,
+};
+
// Record any pending renderer histogram value as a histogram. Pending values
// are set by RegisterChromiumAndroidLinkerRendererHistogram.
BASE_EXPORT void RecordChromiumAndroidLinkerRendererHistogram();
@@ -48,6 +61,9 @@
// created.
BASE_EXPORT void LibraryLoaderExitHook();
+// Return the process type the shared library is loaded in.
+BASE_EXPORT LibraryProcessType GetLibraryProcesssType();
+
} // namespace android
} // namespace base
diff --git a/android/record_histogram.cc b/android/record_histogram.cc
index 9549adc..0df0487 100644
--- a/android/record_histogram.cc
+++ b/android/record_histogram.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/synchronization/lock.h"
+#include "base/time/time.h"
#include "jni/RecordHistogram_jni.h"
namespace base {
@@ -46,20 +47,45 @@
DCHECK(j_histogram_name);
DCHECK(j_histogram_key);
HistogramBase* histogram = FindLocked(j_histogram_key);
- if (histogram)
+ int boundary = static_cast<int>(j_boundary);
+ if (histogram) {
+ DCHECK(histogram->HasConstructionArguments(1, boundary, boundary + 1));
return histogram;
+ }
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- // Note: This caching bypasses the boundary validation that occurs between
- // repeated lookups by the same name. It is up to the caller to ensure that
- // the provided boundary remains consistent.
- int boundary = static_cast<int>(j_boundary);
histogram =
LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1,
HistogramBase::kUmaTargetedHistogramFlag);
return InsertLocked(j_histogram_key, histogram);
}
+ HistogramBase* CustomTimesHistogram(JNIEnv* env,
+ jstring j_histogram_name,
+ jint j_histogram_key,
+ jlong j_min,
+ jlong j_max,
+ jint j_bucket_count) {
+ DCHECK(j_histogram_name);
+ DCHECK(j_histogram_key);
+ HistogramBase* histogram = FindLocked(j_histogram_key);
+ int64 min = static_cast<int64>(j_min);
+ int64 max = static_cast<int64>(j_max);
+ int bucket_count = static_cast<int>(j_bucket_count);
+ if (histogram) {
+ DCHECK(histogram->HasConstructionArguments(min, max, bucket_count));
+ return histogram;
+ }
+
+ std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
+ // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet
+ // is just a convenience for constructing the underlying Histogram with
+ // TimeDelta arguments.
+ histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count,
+ HistogramBase::kUmaTargetedHistogramFlag);
+ return InsertLocked(j_histogram_key, histogram);
+ }
+
private:
HistogramBase* FindLocked(jint j_histogram_key) {
base::AutoLock locked(lock_);
@@ -107,6 +133,20 @@
->Add(sample);
}
+void RecordCustomTimesHistogramMilliseconds(JNIEnv* env,
+ jclass clazz,
+ jstring j_histogram_name,
+ jint j_histogram_key,
+ jlong j_duration,
+ jlong j_min,
+ jlong j_max,
+ jint j_num_buckets) {
+ g_histograms.Get()
+ .CustomTimesHistogram(env, j_histogram_name, j_histogram_key, j_min,
+ j_max, j_num_buckets)
+ ->AddTime(TimeDelta::FromMilliseconds(static_cast<int64>(j_duration)));
+}
+
void Initialize(JNIEnv* env, jclass) {
StatisticsRecorder::Initialize();
}
diff --git a/android/trace_event_binding.cc b/android/trace_event_binding.cc
index b8ce6d9..791b67f 100644
--- a/android/trace_event_binding.cc
+++ b/android/trace_event_binding.cc
@@ -55,7 +55,8 @@
DISALLOW_COPY_AND_ASSIGN(TraceEventDataConverter);
};
-class TraceEnabledObserver : public debug::TraceLog::EnabledStateObserver {
+class TraceEnabledObserver
+ : public trace_event::TraceLog::EnabledStateObserver {
public:
void OnTraceLogEnabled() override {
JNIEnv* env = base::android::AttachCurrentThread();
@@ -72,18 +73,18 @@
} // namespace
static void RegisterEnabledObserver(JNIEnv* env, jclass clazz) {
- bool enabled = debug::TraceLog::GetInstance()->IsEnabled();
+ bool enabled = trace_event::TraceLog::GetInstance()->IsEnabled();
base::android::Java_TraceEvent_setEnabled(env, enabled);
- debug::TraceLog::GetInstance()->AddEnabledStateObserver(
+ trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
g_trace_enabled_state_observer_.Pointer());
}
static void StartATrace(JNIEnv* env, jclass clazz) {
- base::debug::TraceLog::GetInstance()->StartATrace();
+ base::trace_event::TraceLog::GetInstance()->StartATrace();
}
static void StopATrace(JNIEnv* env, jclass clazz) {
- base::debug::TraceLog::GetInstance()->StopATrace();
+ base::trace_event::TraceLog::GetInstance()->StopATrace();
}
static void Instant(JNIEnv* env, jclass clazz,
diff --git a/base.gyp b/base.gyp
index 00244aa..8cd5d6a 100644
--- a/base.gyp
+++ b/base.gyp
@@ -494,10 +494,9 @@
'gmock_unittest.cc',
'guid_unittest.cc',
'hash_unittest.cc',
- 'id_map_unittest.cc',
'i18n/break_iterator_unittest.cc',
- 'i18n/char_iterator_unittest.cc',
'i18n/case_conversion_unittest.cc',
+ 'i18n/char_iterator_unittest.cc',
'i18n/file_util_icu_unittest.cc',
'i18n/icu_string_conversions_unittest.cc',
'i18n/number_formatting_unittest.cc',
@@ -506,6 +505,8 @@
'i18n/string_search_unittest.cc',
'i18n/time_formatting_unittest.cc',
'i18n/timezone_unittest.cc',
+ 'id_map_unittest.cc',
+ 'ios/crb_protocol_observers_unittest.mm',
'ios/device_util_unittest.mm',
'ios/weak_nsobject_unittest.mm',
'json/json_parser_unittest.cc',
@@ -545,17 +546,18 @@
'message_loop/message_pump_glib_unittest.cc',
'message_loop/message_pump_io_ios_unittest.cc',
'message_loop/message_pump_libevent_unittest.cc',
- 'metrics/sample_map_unittest.cc',
- 'metrics/sample_vector_unittest.cc',
'metrics/bucket_ranges_unittest.cc',
'metrics/field_trial_unittest.cc',
'metrics/histogram_base_unittest.cc',
'metrics/histogram_delta_serialization_unittest.cc',
+ 'metrics/histogram_macros_unittest.cc',
'metrics/histogram_snapshot_manager_unittest.cc',
'metrics/histogram_unittest.cc',
+ 'metrics/sample_map_unittest.cc',
+ 'metrics/sample_vector_unittest.cc',
'metrics/sparse_histogram_unittest.cc',
- 'metrics/stats_table_unittest.cc',
'metrics/statistics_recorder_unittest.cc',
+ 'numerics/safe_numerics_unittest.cc',
'observer_list_unittest.cc',
'os_compat_android_unittest.cc',
'path_service_unittest.cc',
@@ -583,7 +585,6 @@
'process/process_util_unittest.cc',
'profiler/tracked_time_unittest.cc',
'rand_util_unittest.cc',
- 'numerics/safe_numerics_unittest.cc',
'scoped_clear_errno_unittest.cc',
'scoped_generic_unittest.cc',
'scoped_native_library_unittest.cc',
@@ -594,13 +595,13 @@
'strings/nullable_string16_unittest.cc',
'strings/safe_sprintf_unittest.cc',
'strings/string16_unittest.cc',
- 'strings/stringprintf_unittest.cc',
'strings/string_number_conversions_unittest.cc',
'strings/string_piece_unittest.cc',
'strings/string_split_unittest.cc',
'strings/string_tokenizer_unittest.cc',
'strings/string_util_unittest.cc',
'strings/stringize_macros_unittest.cc',
+ 'strings/stringprintf_unittest.cc',
'strings/sys_string_conversions_mac_unittest.mm',
'strings/sys_string_conversions_unittest.cc',
'strings/utf_offset_string_conversions_unittest.cc',
@@ -643,6 +644,7 @@
'timer/mock_timer_unittest.cc',
'timer/timer_unittest.cc',
'tools_sanity_unittest.cc',
+ 'trace_event/memory_dump_manager_unittest.cc',
'trace_event/trace_event_argument_unittest.cc',
'trace_event/trace_event_memory_unittest.cc',
'trace_event/trace_event_synthetic_delay_unittest.cc',
@@ -708,8 +710,6 @@
['exclude', '^process/process_unittest\\.cc$'],
['exclude', '^process/process_util_unittest\\.cc$'],
['include', '^process/process_util_unittest_ios\\.cc$'],
- # Requires spawning processes.
- ['exclude', '^metrics/stats_table_unittest\\.cc$'],
# iOS does not use message_pump_libevent.
['exclude', '^message_loop/message_pump_libevent_unittest\\.cc$'],
],
@@ -765,8 +765,8 @@
'sources!': [
'file_descriptor_shuffle_unittest.cc',
'files/dir_reader_posix_unittest.cc',
- 'threading/worker_pool_posix_unittest.cc',
'message_loop/message_pump_libevent_unittest.cc',
+ 'threading/worker_pool_posix_unittest.cc',
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [
@@ -838,9 +838,9 @@
'../testing/gtest.gyp:gtest',
],
'sources': [
- 'threading/thread_perftest.cc',
'message_loop/message_pump_perftest.cc',
'test/run_all_unittests.cc',
+ 'threading/thread_perftest.cc',
'../testing/perf/perf_test.cc'
],
'conditions': [
@@ -912,6 +912,8 @@
'test/gtest_util.h',
'test/gtest_xml_util.cc',
'test/gtest_xml_util.h',
+ 'test/histogram_tester.cc',
+ 'test/histogram_tester.h',
'test/launcher/test_launcher.cc',
'test/launcher/test_launcher.h',
'test/launcher/test_result.cc',
@@ -952,8 +954,6 @@
'test/simple_test_clock.h',
'test/simple_test_tick_clock.cc',
'test/simple_test_tick_clock.h',
- 'test/histogram_tester.cc',
- 'test/histogram_tester.h',
'test/task_runner_test_template.cc',
'test/task_runner_test_template.h',
'test/test_file_util.cc',
@@ -1374,6 +1374,15 @@
'includes': [ '../build/android/java_cpp_template.gypi' ],
},
{
+ # GN: //base:base_android_java_enums_srcjar
+ 'target_name': 'base_java_library_process_type',
+ 'type': 'none',
+ 'variables': {
+ 'source_file': 'android/library_loader/library_loader_hooks.h',
+ },
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
+ },
+ {
# GN: //base:base_java
'target_name': 'base_java',
'type': 'none',
@@ -1384,6 +1393,7 @@
'dependencies': [
'base_java_application_state',
'base_java_library_load_from_apk_status_codes',
+ 'base_java_library_process_type',
'base_java_memory_pressure_level',
'base_native_libraries_gen',
],
diff --git a/base.gypi b/base.gypi
index 6dd6fcf..37a8171 100644
--- a/base.gypi
+++ b/base.gypi
@@ -13,15 +13,6 @@
['base_target==1', {
'sources': [
'../build/build_config.h',
- 'third_party/dmg_fp/dmg_fp.h',
- 'third_party/dmg_fp/g_fmt.cc',
- 'third_party/dmg_fp/dtoa_wrapper.cc',
- 'third_party/icu/icu_utf.cc',
- 'third_party/icu/icu_utf.h',
- 'third_party/nspr/prtime.cc',
- 'third_party/nspr/prtime.h',
- 'third_party/superfasthash/superfasthash.c',
- 'third_party/xdg_mime/xdgmime.h',
'allocator/allocator_extension.cc',
'allocator/allocator_extension.h',
'allocator/type_profiler_control.cc',
@@ -47,10 +38,8 @@
'android/fifo_utils.h',
'android/important_file_writer_android.cc',
'android/important_file_writer_android.h',
- 'android/locale_utils.h',
- 'android/locale_utils.cc',
- 'android/scoped_java_ref.cc',
- 'android/scoped_java_ref.h',
+ 'android/java_handler_thread.cc',
+ 'android/java_handler_thread.h',
'android/jni_android.cc',
'android/jni_android.h',
'android/jni_array.cc',
@@ -64,19 +53,21 @@
'android/jni_utils.h',
'android/jni_weak_ref.cc',
'android/jni_weak_ref.h',
+ 'android/library_loader/library_load_from_apk_status_codes.h',
'android/library_loader/library_loader_hooks.cc',
'android/library_loader/library_loader_hooks.h',
- 'android/library_loader/library_load_from_apk_status_codes.h',
+ 'android/locale_utils.cc',
+ 'android/locale_utils.h',
'android/memory_pressure_listener_android.cc',
'android/memory_pressure_listener_android.h',
- 'android/java_handler_thread.cc',
- 'android/java_handler_thread.h',
'android/path_service_android.cc',
'android/path_service_android.h',
'android/path_utils.cc',
'android/path_utils.h',
'android/record_histogram.cc',
'android/record_histogram.h',
+ 'android/scoped_java_ref.cc',
+ 'android/scoped_java_ref.h',
'android/sys_utils.cc',
'android/sys_utils.h',
'android/thread_utils.h',
@@ -218,8 +209,8 @@
'files/file_util_proxy.h',
'files/file_util_win.cc',
'files/file_win.cc',
- 'files/important_file_writer.h',
'files/important_file_writer.cc',
+ 'files/important_file_writer.h',
'files/memory_mapped_file.cc',
'files/memory_mapped_file.h',
'files/memory_mapped_file_posix.cc',
@@ -239,6 +230,8 @@
'hash.h',
'id_map.h',
'ios/block_types.h',
+ 'ios/crb_protocol_observers.h',
+ 'ios/crb_protocol_observers.mm',
'ios/device_util.h',
'ios/device_util.mm',
'ios/ios_util.h',
@@ -284,8 +277,8 @@
'mac/launchd.h',
'mac/libdispatch_task_runner.cc',
'mac/libdispatch_task_runner.h',
- 'mac/mac_logging.h',
'mac/mac_logging.cc',
+ 'mac/mac_logging.h',
'mac/mac_util.h',
'mac/mac_util.mm',
'mac/mach_logging.cc',
@@ -377,10 +370,6 @@
'message_loop/message_pump_win.cc',
'message_loop/message_pump_win.h',
'message_loop/timer_slack.h',
- 'metrics/sample_map.cc',
- 'metrics/sample_map.h',
- 'metrics/sample_vector.cc',
- 'metrics/sample_vector.h',
'metrics/bucket_ranges.cc',
'metrics/bucket_ranges.h',
'metrics/histogram.cc',
@@ -395,14 +384,14 @@
'metrics/histogram_samples.h',
'metrics/histogram_snapshot_manager.cc',
'metrics/histogram_snapshot_manager.h',
+ 'metrics/sample_map.cc',
+ 'metrics/sample_map.h',
+ 'metrics/sample_vector.cc',
+ 'metrics/sample_vector.h',
'metrics/sparse_histogram.cc',
'metrics/sparse_histogram.h',
'metrics/statistics_recorder.cc',
'metrics/statistics_recorder.h',
- 'metrics/stats_counters.cc',
- 'metrics/stats_counters.h',
- 'metrics/stats_table.cc',
- 'metrics/stats_table.h',
'metrics/user_metrics.cc',
'metrics/user_metrics.h',
'metrics/user_metrics_action.h',
@@ -415,6 +404,10 @@
'nix/mime_util_xdg.h',
'nix/xdg_util.cc',
'nix/xdg_util.h',
+ 'numerics/safe_conversions.h',
+ 'numerics/safe_conversions_impl.h',
+ 'numerics/safe_math.h',
+ 'numerics/safe_math_impl.h',
'observer_list.h',
'observer_list_threadsafe.h',
'os_compat_android.cc',
@@ -435,11 +428,11 @@
'posix/unix_domain_socket_linux.h',
'power_monitor/power_monitor.cc',
'power_monitor/power_monitor.h',
+ 'power_monitor/power_monitor_device_source.cc',
+ 'power_monitor/power_monitor_device_source.h',
'power_monitor/power_monitor_device_source_android.cc',
'power_monitor/power_monitor_device_source_android.h',
'power_monitor/power_monitor_device_source_chromeos.cc',
- 'power_monitor/power_monitor_device_source.cc',
- 'power_monitor/power_monitor_device_source.h',
'power_monitor/power_monitor_device_source_ios.mm',
'power_monitor/power_monitor_device_source_mac.mm',
'power_monitor/power_monitor_device_source_posix.cc',
@@ -460,8 +453,8 @@
'process/launch_mac.cc',
'process/launch_posix.cc',
'process/launch_win.cc',
- 'process/memory.h',
'process/memory.cc',
+ 'process/memory.h',
'process/memory_linux.cc',
'process/memory_mac.mm',
'process/memory_win.cc',
@@ -484,8 +477,8 @@
'process/process_iterator_openbsd.cc',
'process/process_iterator_win.cc',
'process/process_linux.cc',
- 'process/process_metrics.h',
'process/process_metrics.cc',
+ 'process/process_metrics.h',
'process/process_metrics_freebsd.cc',
'process/process_metrics_ios.cc',
'process/process_metrics_linux.cc',
@@ -510,10 +503,6 @@
'rand_util_win.cc',
'run_loop.cc',
'run_loop.h',
- 'numerics/safe_conversions.h',
- 'numerics/safe_conversions_impl.h',
- 'numerics/safe_math.h',
- 'numerics/safe_math_impl.h',
'safe_strerror_posix.cc',
'safe_strerror_posix.h',
'scoped_generic.h',
@@ -540,11 +529,11 @@
'strings/string16.cc',
'strings/string16.h',
'strings/string_number_conversions.cc',
- 'strings/string_split.cc',
- 'strings/string_split.h',
'strings/string_number_conversions.h',
'strings/string_piece.cc',
'strings/string_piece.h',
+ 'strings/string_split.cc',
+ 'strings/string_split.h',
'strings/string_tokenizer.h',
'strings/string_util.cc',
'strings/string_util.h',
@@ -583,8 +572,6 @@
'synchronization/waitable_event_watcher_posix.cc',
'synchronization/waitable_event_watcher_win.cc',
'synchronization/waitable_event_win.cc',
- 'system_monitor/system_monitor.cc',
- 'system_monitor/system_monitor.h',
'sys_byteorder.h',
'sys_info.cc',
'sys_info.h',
@@ -598,12 +585,23 @@
'sys_info_openbsd.cc',
'sys_info_posix.cc',
'sys_info_win.cc',
+ 'system_monitor/system_monitor.cc',
+ 'system_monitor/system_monitor.h',
'task/cancelable_task_tracker.cc',
'task/cancelable_task_tracker.h',
'task_runner.cc',
'task_runner.h',
'task_runner_util.h',
'template_util.h',
+ 'third_party/dmg_fp/dmg_fp.h',
+ 'third_party/dmg_fp/dtoa_wrapper.cc',
+ 'third_party/dmg_fp/g_fmt.cc',
+ 'third_party/icu/icu_utf.cc',
+ 'third_party/icu/icu_utf.h',
+ 'third_party/nspr/prtime.cc',
+ 'third_party/nspr/prtime.h',
+ 'third_party/superfasthash/superfasthash.c',
+ 'third_party/xdg_mime/xdgmime.h',
'thread_task_runner_handle.cc',
'thread_task_runner_handle.h',
'threading/non_thread_safe.h',
@@ -638,12 +636,12 @@
'threading/thread_local_storage_posix.cc',
'threading/thread_local_storage_win.cc',
'threading/thread_local_win.cc',
- 'threading/thread_restrictions.h',
'threading/thread_restrictions.cc',
+ 'threading/thread_restrictions.h',
'threading/watchdog.cc',
'threading/watchdog.h',
- 'threading/worker_pool.h',
'threading/worker_pool.cc',
+ 'threading/worker_pool.h',
'threading/worker_pool_posix.cc',
'threading/worker_pool_posix.h',
'threading/worker_pool_win.cc',
@@ -669,6 +667,11 @@
'timer/mock_timer.h',
'timer/timer.cc',
'timer/timer.h',
+ 'trace_event/memory_dump_manager.cc',
+ 'trace_event/memory_dump_manager.h',
+ 'trace_event/memory_dump_provider.h',
+ 'trace_event/process_memory_dump.cc',
+ 'trace_event/process_memory_dump.h',
'trace_event/trace_event.h',
'trace_event/trace_event_android.cc',
'trace_event/trace_event_argument.cc',
@@ -689,10 +692,10 @@
'tracking_info.cc',
'tracking_info.h',
'tuple.h',
- 'values.cc',
- 'values.h',
'value_conversions.cc',
'value_conversions.h',
+ 'values.cc',
+ 'values.h',
'version.cc',
'version.h',
'vlog.cc',
@@ -795,6 +798,7 @@
'files/file_util_posix.cc',
'files/file_util_proxy.cc',
'files/important_file_writer.cc',
+ 'files/scoped_temp_dir.cc',
'memory/shared_memory_posix.cc',
'native_library_posix.cc',
'path_service.cc',
@@ -808,7 +812,6 @@
'process/process_posix.cc',
'rand_util_posix.cc',
'scoped_native_library.cc',
- 'files/scoped_temp_dir.cc',
'sys_info.cc',
'sys_info_posix.cc',
'third_party/dynamic_annotations/dynamic_annotations.c',
@@ -819,10 +822,10 @@
}],
['OS == "android" and _toolset == "target" and >(nacl_untrusted_build)==0', {
'sources': [
- 'memory/discardable_memory_ashmem_allocator.cc',
- 'memory/discardable_memory_ashmem_allocator.h',
'memory/discardable_memory_ashmem.cc',
'memory/discardable_memory_ashmem.h',
+ 'memory/discardable_memory_ashmem_allocator.cc',
+ 'memory/discardable_memory_ashmem_allocator.h',
],
}],
['OS == "android" and >(nacl_untrusted_build)==0', {
diff --git a/base_unittests.isolate b/base_unittests.isolate
index 0822b24..2e33cc0 100644
--- a/base_unittests.isolate
+++ b/base_unittests.isolate
@@ -58,7 +58,7 @@
],
},
}],
- ['OS=="mac" and asan==1', {
+ ['OS=="mac" and asan==1 and fastbuild==0', {
'variables': {
'files': [
'<(PRODUCT_DIR)/base_unittests.dSYM/',
diff --git a/bind_helpers.h b/bind_helpers.h
index f8e89bd..c49b5b8 100644
--- a/bind_helpers.h
+++ b/bind_helpers.h
@@ -535,23 +535,6 @@
template <typename List1, typename List2>
using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
-template <size_t n, typename List>
-struct NthTypeImpl;
-
-template <size_t n, typename T, typename... Types>
-struct NthTypeImpl<n, TypeList<T, Types...>>
- : NthTypeImpl<n - 1, TypeList<Types...>> {
-};
-
-template <typename T, typename... Types>
-struct NthTypeImpl<0, TypeList<T, Types...>> {
- typedef T Type;
-};
-
-// A type-level function that extracts |n|th type from a TypeList.
-template <size_t n, typename List>
-using NthType = typename NthTypeImpl<n, List>::Type;
-
// Used for MakeFunctionType implementation.
template <typename R, typename ArgList>
struct MakeFunctionTypeImpl;
diff --git a/containers/hash_tables.h b/containers/hash_tables.h
index 736e892..6bf029e 100644
--- a/containers/hash_tables.h
+++ b/containers/hash_tables.h
@@ -45,7 +45,7 @@
#undef __DEPRECATED
#endif
-#if defined(OS_ANDROID) && defined(USE_STLPORT)
+#if defined(OS_ANDROID)
#include <hash_map>
#include <hash_set>
#define BASE_HASH_IMPL_NAMESPACE std
@@ -84,7 +84,7 @@
}
};
-#if !defined(USE_STLPORT)
+#if !defined(OS_ANDROID)
// The GNU C++ library provides identity hash functions for many integral types,
// but not for |long long|. This hash function will truncate if |size_t| is
// narrower than |long long|. This is probably good enough for what we will
@@ -102,7 +102,7 @@
DEFINE_TRIVIAL_HASH(unsigned long long);
#undef DEFINE_TRIVIAL_HASH
-#endif // !defined(USE_STLPORT)
+#endif // !defined(OS_ANDROID)
// Implement string hash functions so that strings of various flavors can
// be used as keys in STL maps and sets. The hash algorithm comes from the
diff --git a/files/file_path.h b/files/file_path.h
index 67bbb4b..93f9ec9 100644
--- a/files/file_path.h
+++ b/files/file_path.h
@@ -53,7 +53,7 @@
// between char[]-based pathnames on POSIX systems and wchar_t[]-based
// pathnames on Windows.
//
-// Paths can't contain NULs as a precaution agaist premature truncation.
+// As a precaution against premature truncation, paths can't contain NULs.
//
// Because a FilePath object should not be instantiated at the global scope,
// instead, use a FilePath::CharType[] and initialize it with
@@ -83,9 +83,9 @@
// in case it ever comes across such a system. FilePath needs this support
// for Windows UNC paths, anyway.
// References:
-// The Open Group Base Specifications Issue 7, sections 3.266 ("Pathname")
+// The Open Group Base Specifications Issue 7, sections 3.267 ("Pathname")
// and 4.12 ("Pathname Resolution"), available at:
-// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_266
+// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_267
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12
//
// - Windows treats c:\\ the same way it treats \\. This was intended to
diff --git a/files/file_path_watcher_linux.cc b/files/file_path_watcher_linux.cc
index 60267df..06c517a 100644
--- a/files/file_path_watcher_linux.cc
+++ b/files/file_path_watcher_linux.cc
@@ -200,7 +200,7 @@
CHECK_LE(0, shutdown_fd);
CHECK_GT(FD_SETSIZE, shutdown_fd);
- debug::TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
+ trace_event::TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
while (true) {
fd_set rfds;
diff --git a/files/file_util_linux.cc b/files/file_util_linux.cc
index 532962f..b230fd9 100644
--- a/files/file_util_linux.cc
+++ b/files/file_util_linux.cc
@@ -10,21 +10,6 @@
#include "base/files/file_path.h"
-// Make sure some of the newer macros from magic.h are defined.
-// TODO(mostynb@opera.com): remove this after 2014.
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-#ifndef HUGETLBFS_MAGIC
-#define HUGETLBFS_MAGIC 0x958458f6
-#endif
-#ifndef RAMFS_MAGIC
-#define RAMFS_MAGIC 0x858458f6
-#endif
-#ifndef TMPFS_MAGIC
-#define TMPFS_MAGIC 0x01021994
-#endif
-
namespace base {
bool GetFileSystemType(const FilePath& path, FileSystemType* type) {
diff --git a/files/file_util_unittest.cc b/files/file_util_unittest.cc
index 313ed03..af932ce 100644
--- a/files/file_util_unittest.cc
+++ b/files/file_util_unittest.cc
@@ -30,6 +30,7 @@
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_file_util.h"
#include "base/threading/platform_thread.h"
@@ -326,6 +327,13 @@
// |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
FilePath base_a = temp_dir_.path().Append(FPL("base_a"));
+#if defined(OS_WIN)
+ // TEMP can have a lower case drive letter.
+ string16 temp_base_a = base_a.value();
+ ASSERT_FALSE(temp_base_a.empty());
+ *temp_base_a.begin() = base::ToUpperASCII(*temp_base_a.begin());
+ base_a = FilePath(temp_base_a);
+#endif
ASSERT_TRUE(CreateDirectory(base_a));
FilePath sub_a = base_a.Append(FPL("sub_a"));
@@ -428,6 +436,7 @@
TEST_F(FileUtilTest, DevicePathToDriveLetter) {
// Get a drive letter.
std::wstring real_drive_letter = temp_dir_.path().value().substr(0, 2);
+ StringToUpperASCII(&real_drive_letter);
if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
LOG(ERROR) << "Can't get a drive letter to test with.";
return;
@@ -1388,19 +1397,15 @@
path.value().c_str(),
read_only ? (attrs | FILE_ATTRIBUTE_READONLY) :
(attrs & ~FILE_ATTRIBUTE_READONLY)));
- // Files in the temporary directory should not be indexed ever. If this
- // assumption change, fix this unit test accordingly.
- // FILE_ATTRIBUTE_NOT_CONTENT_INDEXED doesn't exist on XP.
+
DWORD expected = read_only ?
((attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY)) |
FILE_ATTRIBUTE_READONLY) :
(attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY));
- // TODO(ripp@yandex-team.ru): this seems out of place here. If we really think
- // it is important to verify that temp files are not indexed there should be
- // a dedicated test for that (create a file, inspect the attributes)
- if (win::GetVersion() >= win::VERSION_VISTA)
- expected |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
- attrs = GetFileAttributes(path.value().c_str());
+
+ // Ignore FILE_ATTRIBUTE_NOT_CONTENT_INDEXED if present.
+ attrs = GetFileAttributes(path.value().c_str()) &
+ ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
ASSERT_EQ(expected, attrs);
#else
// On all other platforms, it involves removing/setting the write bit.
diff --git a/i18n/time_formatting.cc b/i18n/time_formatting.cc
index 917ba43..15b34a3 100644
--- a/i18n/time_formatting.cc
+++ b/i18n/time_formatting.cc
@@ -106,6 +106,12 @@
return TimeFormat(formatter.get(), time);
}
+string16 TimeFormatShortDateAndTimeWithTimeZone(const Time& time) {
+ scoped_ptr<icu::DateFormat> formatter(icu::DateFormat::createDateTimeInstance(
+ icu::DateFormat::kShort, icu::DateFormat::kLong));
+ return TimeFormat(formatter.get(), time);
+}
+
string16 TimeFormatFriendlyDateAndTime(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull));
diff --git a/i18n/time_formatting.h b/i18n/time_formatting.h
index 226d1a9..2053c0b 100644
--- a/i18n/time_formatting.h
+++ b/i18n/time_formatting.h
@@ -48,6 +48,11 @@
// Returns a numeric date and time such as "12/13/52 2:44:30 PM".
BASE_I18N_EXPORT string16 TimeFormatShortDateAndTime(const Time& time);
+// Returns a numeric date and time with time zone such as
+// "12/13/52 2:44:30 PM PST".
+BASE_I18N_EXPORT string16
+TimeFormatShortDateAndTimeWithTimeZone(const Time& time);
+
// Formats a time in a friendly sentence format, e.g.
// "Monday, March 6, 2008 2:44:30 PM".
BASE_I18N_EXPORT string16 TimeFormatFriendlyDateAndTime(const Time& time);
diff --git a/i18n/time_formatting_unittest.cc b/i18n/time_formatting_unittest.cc
index 0c2a6e6..4739b62 100644
--- a/i18n/time_formatting_unittest.cc
+++ b/i18n/time_formatting_unittest.cc
@@ -5,10 +5,13 @@
#include "base/i18n/time_formatting.h"
#include "base/i18n/rtl.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/icu/source/common/unicode/uversion.h"
+#include "third_party/icu/source/i18n/unicode/calendar.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
namespace base {
namespace {
@@ -18,6 +21,13 @@
15, 42, 7, 0 // 15:42:07.000
};
+base::string16 GetShortTimeZone() {
+ scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+ icu::UnicodeString name;
+ zone->getDisplayName(true, icu::TimeZone::SHORT, name);
+ return base::string16(name.getBuffer(), name.length());
+}
+
TEST(TimeFormattingTest, TimeFormatTimeOfDayDefault12h) {
// Test for a locale defaulted to 12h clock.
// As an instance, we use third_party/icu/source/data/locales/en.txt.
@@ -129,6 +139,8 @@
EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM"),
TimeFormatShortDateAndTime(time));
+ EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM ") + GetShortTimeZone(),
+ TimeFormatShortDateAndTimeWithTimeZone(time));
EXPECT_EQ(ASCIIToUTF16("Saturday, April 30, 2011 at 3:42:07 PM"),
TimeFormatFriendlyDateAndTime(time));
@@ -148,6 +160,8 @@
EXPECT_EQ(ASCIIToUTF16("30/04/2011"), TimeFormatShortDateNumeric(time));
EXPECT_EQ(ASCIIToUTF16("30/04/2011 15:42:07"),
TimeFormatShortDateAndTime(time));
+ EXPECT_EQ(ASCIIToUTF16("30/04/2011 15:42:07 ") + GetShortTimeZone(),
+ TimeFormatShortDateAndTimeWithTimeZone(time));
EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011 15:42:07"),
TimeFormatFriendlyDateAndTime(time));
EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011"),
diff --git a/ios/crb_protocol_observers.h b/ios/crb_protocol_observers.h
new file mode 100644
index 0000000..15d1656
--- /dev/null
+++ b/ios/crb_protocol_observers.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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 BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
+#define BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
+
+#import <Foundation/Foundation.h>
+
+typedef void (^ExecutionWithObserverBlock)(id);
+
+// Implements a container for observers that implement a specific Objective-C
+// protocol. The container forwards method invocations to its contained
+// observers, so that sending a message to all the observers is as simple as
+// sending the message to the container.
+@interface CRBProtocolObservers : NSObject
+
+// The Objective-C protocol that the observers in this container conform to.
+@property(nonatomic, readonly) Protocol* protocol;
+
+// Returns a CRBProtocolObservers container for observers that conform to
+// |protocol|.
++ (CRBProtocolObservers*)observersWithProtocol:(Protocol*)protocol;
+
+// Adds |observer| to this container.
+- (void)addObserver:(id)observer;
+
+// Remove |observer| from this container.
+- (void)removeObserver:(id)observer;
+
+// Executes callback on every observer. |callback| cannot be nil.
+- (void)executeOnObservers:(ExecutionWithObserverBlock)callback;
+
+@end
+
+#endif // BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
diff --git a/ios/crb_protocol_observers.mm b/ios/crb_protocol_observers.mm
new file mode 100644
index 0000000..ee9e23f
--- /dev/null
+++ b/ios/crb_protocol_observers.mm
@@ -0,0 +1,99 @@
+// Copyright 2014 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 "base/ios/crb_protocol_observers.h"
+
+#include <objc/runtime.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+
+@interface CRBProtocolObservers ()
+
+// Designated initializer.
+- (id)initWithProtocol:(Protocol*)protocol;
+
+@end
+
+@implementation CRBProtocolObservers {
+ base::scoped_nsobject<Protocol> _protocol;
+ base::scoped_nsobject<NSHashTable> _observers;
+}
+
++ (CRBProtocolObservers*)observersWithProtocol:(Protocol*)protocol {
+ return [[[self alloc] initWithProtocol:protocol] autorelease];
+}
+
+- (id)init {
+ NOTREACHED();
+ return nil;
+}
+
+- (id)initWithProtocol:(Protocol*)protocol {
+ self = [super init];
+ if (self) {
+ _protocol.reset([protocol retain]);
+ _observers.reset([[NSHashTable weakObjectsHashTable] retain]);
+ }
+ return self;
+}
+
+- (Protocol*)protocol {
+ return _protocol.get();
+}
+
+- (void)addObserver:(id)observer {
+ DCHECK([observer conformsToProtocol:self.protocol]);
+ [_observers addObject:observer];
+}
+
+- (void)removeObserver:(id)observer {
+ [_observers removeObject:observer];
+}
+
+#pragma mark - NSObject
+
+- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
+ NSMethodSignature* signature = [super methodSignatureForSelector:selector];
+ if (signature)
+ return signature;
+
+ // Look for a required method in the protocol. protocol_getMethodDescription
+ // returns a struct whose fields are null if a method for the selector was
+ // not found.
+ struct objc_method_description description =
+ protocol_getMethodDescription(self.protocol, selector, YES, YES);
+ if (description.types)
+ return [NSMethodSignature signatureWithObjCTypes:description.types];
+
+ // Look for an optional method in the protocol.
+ description = protocol_getMethodDescription(self.protocol, selector, NO, YES);
+ if (description.types)
+ return [NSMethodSignature signatureWithObjCTypes:description.types];
+
+ // There is neither a required nor optional method with this selector in the
+ // protocol, so invoke -[NSObject doesNotRecognizeSelector:] to raise
+ // NSInvalidArgumentException.
+ [self doesNotRecognizeSelector:selector];
+ return nil;
+}
+
+- (void)forwardInvocation:(NSInvocation*)invocation {
+ SEL selector = [invocation selector];
+ base::scoped_nsobject<NSArray> observers([[_observers allObjects] retain]);
+ for (id observer in observers.get()) {
+ if ([observer respondsToSelector:selector])
+ [invocation invokeWithTarget:observer];
+ }
+}
+
+- (void)executeOnObservers:(ExecutionWithObserverBlock)callback {
+ DCHECK(callback);
+ base::scoped_nsobject<NSArray> observers([[_observers allObjects] retain]);
+ for (id observer in observers.get()) {
+ callback(observer);
+ }
+}
+
+@end
diff --git a/ios/crb_protocol_observers_unittest.mm b/ios/crb_protocol_observers_unittest.mm
new file mode 100644
index 0000000..d235c98
--- /dev/null
+++ b/ios/crb_protocol_observers_unittest.mm
@@ -0,0 +1,159 @@
+// Copyright 2014 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 "base/ios/crb_protocol_observers.h"
+#include "base/ios/weak_nsobject.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/mac/scoped_nsobject.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+@protocol TestObserver
+
+@required
+- (void)requiredMethod;
+- (void)reset;
+
+@optional
+- (void)optionalMethod;
+
+@end
+
+// Implements only the required methods in the TestObserver protocol.
+@interface TestPartialObserver : NSObject<TestObserver>
+@property(nonatomic, readonly) BOOL requiredMethodInvoked;
+@end
+
+// Implements all the methods in the TestObserver protocol.
+@interface TestCompleteObserver : TestPartialObserver<TestObserver>
+@property(nonatomic, readonly) BOOL optionalMethodInvoked;
+@end
+
+namespace {
+
+class CRBProtocolObserversTest : public PlatformTest {
+ public:
+ CRBProtocolObserversTest() {}
+
+ protected:
+ void SetUp() override {
+ PlatformTest::SetUp();
+
+ observers_.reset([[CRBProtocolObservers observersWithProtocol:
+ @protocol(TestObserver)] retain]);
+
+ partial_observer_.reset([[TestPartialObserver alloc] init]);
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+
+ complete_observer_.reset([[TestCompleteObserver alloc] init]);
+ EXPECT_FALSE([complete_observer_ requiredMethodInvoked]);
+ EXPECT_FALSE([complete_observer_ optionalMethodInvoked]);
+ }
+
+ base::scoped_nsobject<id> observers_;
+ base::scoped_nsobject<TestPartialObserver> partial_observer_;
+ base::scoped_nsobject<TestCompleteObserver> complete_observer_;
+};
+
+// Verifies basic functionality of -[CRBProtocolObservers addObserver:] and
+// -[CRBProtocolObservers removeObserver:].
+TEST_F(CRBProtocolObserversTest, AddRemoveObserver) {
+ // Add an observer and verify that the CRBProtocolObservers instance forwards
+ // an invocation to it.
+ [observers_ addObserver:partial_observer_];
+ [observers_ requiredMethod];
+ EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+
+ [partial_observer_ reset];
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+
+ // Remove the observer and verify that the CRBProtocolObservers instance no
+ // longer forwards an invocation to it.
+ [observers_ removeObserver:partial_observer_];
+ [observers_ requiredMethod];
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers correctly forwards the invocation of a
+// required method in the protocol.
+TEST_F(CRBProtocolObserversTest, RequiredMethods) {
+ [observers_ addObserver:partial_observer_];
+ [observers_ addObserver:complete_observer_];
+ [observers_ requiredMethod];
+ EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+ EXPECT_TRUE([complete_observer_ requiredMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers correctly forwards the invocation of an
+// optional method in the protocol.
+TEST_F(CRBProtocolObserversTest, OptionalMethods) {
+ [observers_ addObserver:partial_observer_];
+ [observers_ addObserver:complete_observer_];
+ [observers_ optionalMethod];
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+ EXPECT_FALSE([complete_observer_ requiredMethodInvoked]);
+ EXPECT_TRUE([complete_observer_ optionalMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers only holds a weak reference to an
+// observer.
+TEST_F(CRBProtocolObserversTest, WeakReference) {
+ base::WeakNSObject<TestPartialObserver> weak_observer(
+ partial_observer_);
+ EXPECT_TRUE(weak_observer);
+
+ [observers_ addObserver:partial_observer_];
+
+ {
+ // Need an autorelease pool here, because
+ // -[CRBProtocolObservers forwardInvocation:] creates a temporary
+ // autoreleased array that holds all the observers.
+ base::mac::ScopedNSAutoreleasePool pool;
+ [observers_ requiredMethod];
+ EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+ }
+
+ partial_observer_.reset();
+ EXPECT_FALSE(weak_observer.get());
+}
+
+} // namespace
+
+@implementation TestPartialObserver {
+ BOOL _requiredMethodInvoked;
+}
+
+- (BOOL)requiredMethodInvoked {
+ return _requiredMethodInvoked;
+}
+
+- (void)requiredMethod {
+ _requiredMethodInvoked = YES;
+}
+
+- (void)reset {
+ _requiredMethodInvoked = NO;
+}
+
+@end
+
+@implementation TestCompleteObserver {
+ BOOL _optionalMethodInvoked;
+}
+
+- (BOOL)optionalMethodInvoked {
+ return _optionalMethodInvoked;
+}
+
+- (void)optionalMethod {
+ _optionalMethodInvoked = YES;
+}
+
+- (void)reset {
+ [super reset];
+ _optionalMethodInvoked = NO;
+}
+
+@end
diff --git a/logging.h b/logging.h
index aa243a9..cc0a5aa 100644
--- a/logging.h
+++ b/logging.h
@@ -350,7 +350,7 @@
((verboselevel) <= ::logging::GetVlogLevel(__FILE__))
// Helper macro which avoids evaluating the arguments to a stream if
-// the condition doesn't hold.
+// the condition doesn't hold. Condition is evaluated once and only once.
#define LAZY_STREAM(stream, condition) \
!(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream)
diff --git a/mac/sdk_forward_declarations.h b/mac/sdk_forward_declarations.h
index faa36ea..2795b19 100644
--- a/mac/sdk_forward_declarations.h
+++ b/mac/sdk_forward_declarations.h
@@ -219,6 +219,55 @@
- (void)windowDidFailToExitFullScreen:(NSWindow*)window;
@end
+BASE_EXPORT extern "C" NSString* const CBAdvertisementDataServiceDataKey;
+
+enum {
+ CBPeripheralStateDisconnected = 0,
+ CBPeripheralStateConnecting,
+ CBPeripheralStateConnected,
+};
+typedef NSInteger CBPeripheralState;
+
+@interface CBPeripheral : NSObject
+@property(readonly, nonatomic) CFUUIDRef UUID;
+@property(retain, readonly) NSString* name;
+@property(readonly) BOOL isConnected;
+@end
+
+enum {
+ CBCentralManagerStateUnknown = 0,
+ CBCentralManagerStateResetting,
+ CBCentralManagerStateUnsupported,
+ CBCentralManagerStateUnauthorized,
+ CBCentralManagerStatePoweredOff,
+ CBCentralManagerStatePoweredOn,
+};
+typedef NSInteger CBCentralManagerState;
+
+@protocol CBCentralManagerDelegate;
+
+@interface CBCentralManager : NSObject
+@property(readonly) CBCentralManagerState state;
+- (id)initWithDelegate:(id<CBCentralManagerDelegate>)delegate
+ queue:(dispatch_queue_t)queue;
+- (void)scanForPeripheralsWithServices:(NSArray*)serviceUUIDs
+ options:(NSDictionary*)options;
+- (void)stopScan;
+@end
+
+@protocol CBCentralManagerDelegate<NSObject>
+- (void)centralManagerDidUpdateState:(CBCentralManager*)central;
+- (void)centralManager:(CBCentralManager*)central
+ didDiscoverPeripheral:(CBPeripheral*)peripheral
+ advertisementData:(NSDictionary*)advertisementData
+ RSSI:(NSNumber*)RSSI;
+@end
+
+@interface CBUUID : NSObject
+@property(nonatomic, readonly) NSData* data;
++ (CBUUID*)UUIDWithString:(NSString*)theString;
+@end
+
#endif // MAC_OS_X_VERSION_10_7
#if !defined(MAC_OS_X_VERSION_10_8) || \
@@ -232,6 +281,10 @@
- (CGColorRef)CGColor;
@end
+@interface NSUUID : NSObject
+- (NSString*)UUIDString;
+@end
+
#endif // MAC_OS_X_VERSION_10_8
@@ -304,6 +357,12 @@
NSWorkspaceLaunchWithErrorPresentation = 0x00000040
};
+@interface CBPeripheral (MavericksSDK)
+@property(readonly, nonatomic) NSUUID* identifier;
+@end
+
+BASE_EXPORT extern "C" NSString* const CBAdvertisementDataIsConnectable;
+
#else // !MAC_OS_X_VERSION_10_9
typedef enum {
@@ -345,6 +404,10 @@
BASE_EXPORT extern "C" NSString* const NSAppearanceNameVibrantDark;
+@interface CBUUID (YosemiteSDK)
+- (NSString*)UUIDString;
+@end
+
#endif // MAC_OS_X_VERSION_10_10
#endif // BASE_MAC_SDK_FORWARD_DECLARATIONS_H_
diff --git a/mac/sdk_forward_declarations.mm b/mac/sdk_forward_declarations.mm
index 7a57032..4edc710 100644
--- a/mac/sdk_forward_declarations.mm
+++ b/mac/sdk_forward_declarations.mm
@@ -23,6 +23,8 @@
NSString* const NSWindowDidChangeBackingPropertiesNotification =
@"NSWindowDidChangeBackingPropertiesNotification";
+NSString* const CBAdvertisementDataServiceDataKey = @"kCBAdvDataServiceData";
+
#endif // MAC_OS_X_VERSION_10_7
// Replicate specific 10.9 SDK declarations for building with prior SDKs.
@@ -32,6 +34,8 @@
NSString* const NSWindowDidChangeOcclusionStateNotification =
@"NSWindowDidChangeOcclusionStateNotification";
+NSString* const CBAdvertisementDataIsConnectable = @"kCBAdvDataIsConnectable";
+
#endif // MAC_OS_X_VERSION_10_9
// Replicate specific 10.10 SDK declarations for building with prior SDKs.
diff --git a/macros.h b/macros.h
index 15408bc..3ea576c 100644
--- a/macros.h
+++ b/macros.h
@@ -63,7 +63,7 @@
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif
-#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+#define arraysize(array) (sizeof(::ArraySizeHelper(array)))
// Use implicit_cast as a safe version of static_cast or const_cast
diff --git a/memory/discardable_memory.h b/memory/discardable_memory.h
index d8b7a58..c49a99f 100644
--- a/memory/discardable_memory.h
+++ b/memory/discardable_memory.h
@@ -89,10 +89,6 @@
// Create a DiscardableMemory instance with preferred type and |size|.
static scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size);
- // Discardable memory implementations might use this to release memory
- // or resources assigned to instances that have been purged.
- static void ReleaseFreeMemory();
-
// Discardable memory implementations might allow an elevated usage level
// while in frequent use. Call this to have the usage reduced to the base
// level. Returns true if there's no need to call this again until
@@ -118,12 +114,6 @@
// Returns the memory address held by this object. The object must be locked
// before calling this. Otherwise, this will cause a DCHECK error.
virtual void* Memory() const = 0;
-
- // Testing utility calls.
-
- // Purge all discardable memory in the system. This call has global effects
- // across all running processes, so it should only be used for testing!
- static void PurgeForTesting();
};
} // namespace base
diff --git a/memory/discardable_memory_android.cc b/memory/discardable_memory_android.cc
index de71124..27b390f 100644
--- a/memory/discardable_memory_android.cc
+++ b/memory/discardable_memory_android.cc
@@ -44,11 +44,6 @@
} // namespace
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -104,11 +99,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- g_shared_state.Pointer()->manager.PurgeAll();
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/memory/discardable_memory_ashmem.cc b/memory/discardable_memory_ashmem.cc
index df0697c..a590e53 100644
--- a/memory/discardable_memory_ashmem.cc
+++ b/memory/discardable_memory_ashmem.cc
@@ -71,9 +71,5 @@
ashmem_chunk_.reset();
}
-bool DiscardableMemoryAshmem::IsMemoryResident() const {
- return true;
-}
-
} // namespace internal
} // namespace base
diff --git a/memory/discardable_memory_ashmem.h b/memory/discardable_memory_ashmem.h
index 100655b..1269cc2 100644
--- a/memory/discardable_memory_ashmem.h
+++ b/memory/discardable_memory_ashmem.h
@@ -38,7 +38,6 @@
bool AllocateAndAcquireLock() override;
void ReleaseLock() override;
void Purge() override;
- bool IsMemoryResident() const override;
private:
const size_t bytes_;
diff --git a/memory/discardable_memory_emulated.cc b/memory/discardable_memory_emulated.cc
index 4303400..b12d7ce 100644
--- a/memory/discardable_memory_emulated.cc
+++ b/memory/discardable_memory_emulated.cc
@@ -68,11 +68,6 @@
g_manager.Pointer()->ReduceMemoryUsageUntilWithinLimit(bytes);
}
-// static
-void DiscardableMemoryEmulated::PurgeForTesting() {
- g_manager.Pointer()->PurgeAll();
-}
-
bool DiscardableMemoryEmulated::Initialize() {
return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
}
@@ -113,9 +108,5 @@
memory_.reset();
}
-bool DiscardableMemoryEmulated::IsMemoryResident() const {
- return true;
-}
-
} // namespace internal
} // namespace base
diff --git a/memory/discardable_memory_emulated.h b/memory/discardable_memory_emulated.h
index 150c1ab..aa01a9d 100644
--- a/memory/discardable_memory_emulated.h
+++ b/memory/discardable_memory_emulated.h
@@ -26,8 +26,6 @@
// unavailable in kernel space. crbug.com/400423
BASE_EXPORT static void ReduceMemoryUsageUntilWithinLimit(size_t bytes);
- static void PurgeForTesting();
-
bool Initialize();
// Overridden from DiscardableMemory:
@@ -39,7 +37,6 @@
bool AllocateAndAcquireLock() override;
void ReleaseLock() override {}
void Purge() override;
- bool IsMemoryResident() const override;
private:
const size_t bytes_;
diff --git a/memory/discardable_memory_linux.cc b/memory/discardable_memory_linux.cc
index 9b4e940..977b029 100644
--- a/memory/discardable_memory_linux.cc
+++ b/memory/discardable_memory_linux.cc
@@ -11,11 +11,6 @@
namespace base {
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -61,10 +56,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/memory/discardable_memory_mac.cc b/memory/discardable_memory_mac.cc
index 18cf80a..c8669a6 100644
--- a/memory/discardable_memory_mac.cc
+++ b/memory/discardable_memory_mac.cc
@@ -14,11 +14,6 @@
namespace base {
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -72,11 +67,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- internal::DiscardableMemoryMach::PurgeForTesting();
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/memory/discardable_memory_mach.cc b/memory/discardable_memory_mach.cc
index 5fc43f2..d96de79 100644
--- a/memory/discardable_memory_mach.cc
+++ b/memory/discardable_memory_mach.cc
@@ -63,12 +63,6 @@
g_manager.Pointer()->Unregister(this);
}
-// static
-void DiscardableMemoryMach::PurgeForTesting() {
- int state = 0;
- vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
-}
-
bool DiscardableMemoryMach::Initialize() {
return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
}
@@ -154,9 +148,5 @@
memory_.reset();
}
-bool DiscardableMemoryMach::IsMemoryResident() const {
- return true;
-}
-
} // namespace internal
} // namespace base
diff --git a/memory/discardable_memory_mach.h b/memory/discardable_memory_mach.h
index af2191f..b3b4b48 100644
--- a/memory/discardable_memory_mach.h
+++ b/memory/discardable_memory_mach.h
@@ -20,8 +20,6 @@
explicit DiscardableMemoryMach(size_t bytes);
~DiscardableMemoryMach() override;
- static void PurgeForTesting();
-
bool Initialize();
// Overridden from DiscardableMemory:
@@ -33,7 +31,6 @@
bool AllocateAndAcquireLock() override;
void ReleaseLock() override;
void Purge() override;
- bool IsMemoryResident() const override;
private:
mac::ScopedMachVM memory_;
diff --git a/memory/discardable_memory_manager.cc b/memory/discardable_memory_manager.cc
index 09e63e3..cbbdb47 100644
--- a/memory/discardable_memory_manager.cc
+++ b/memory/discardable_memory_manager.cc
@@ -51,34 +51,6 @@
hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time;
}
-void DiscardableMemoryManager::ReleaseFreeMemory() {
- TRACE_EVENT0("base", "DiscardableMemoryManager::ReleaseFreeMemory");
-
- AutoLock lock(lock_);
- size_t bytes_allocated_before_releasing_memory = bytes_allocated_;
- for (auto& entry : allocations_) {
- Allocation* allocation = entry.first;
- AllocationInfo* info = &entry.second;
-
- if (!info->purgable)
- continue;
-
- // Skip if memory is still resident, otherwise purge and adjust
- // |bytes_allocated_|.
- if (allocation->IsMemoryResident())
- continue;
-
- size_t bytes_purgable = info->bytes;
- DCHECK_LE(bytes_purgable, bytes_allocated_);
- bytes_allocated_ -= bytes_purgable;
- info->purgable = false;
- allocation->Purge();
- }
-
- if (bytes_allocated_ != bytes_allocated_before_releasing_memory)
- BytesAllocatedChanged(bytes_allocated_);
-}
-
bool DiscardableMemoryManager::ReduceMemoryUsage() {
return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit();
}
diff --git a/memory/discardable_memory_manager.h b/memory/discardable_memory_manager.h
index 8bf9289..43737f8 100644
--- a/memory/discardable_memory_manager.h
+++ b/memory/discardable_memory_manager.h
@@ -31,10 +31,6 @@
// is acquired on the allocation.
virtual void Purge() = 0;
- // Check if allocated memory is still resident. It is illegal to call this
- // while a lock is acquired on the allocation.
- virtual bool IsMemoryResident() const = 0;
-
protected:
virtual ~DiscardableMemoryManagerAllocation() {}
};
@@ -72,9 +68,6 @@
void SetHardMemoryLimitExpirationTime(
TimeDelta hard_memory_limit_expiration_time);
- // This will make sure that all purged memory is released to the OS.
- void ReleaseFreeMemory();
-
// This will attempt to reduce memory footprint until within soft memory
// limit. Returns true if there's no need to call this again until allocations
// have been used.
diff --git a/memory/discardable_memory_manager_unittest.cc b/memory/discardable_memory_manager_unittest.cc
index 9f06e37..6717f09 100644
--- a/memory/discardable_memory_manager_unittest.cc
+++ b/memory/discardable_memory_manager_unittest.cc
@@ -33,10 +33,6 @@
DCHECK(is_allocated_);
is_allocated_ = false;
}
- bool IsMemoryResident() const override {
- DCHECK(is_allocated_);
- return true;
- }
bool is_locked() const { return is_locked_; }
diff --git a/memory/discardable_memory_shmem.cc b/memory/discardable_memory_shmem.cc
index 416fcf2..9056279 100644
--- a/memory/discardable_memory_shmem.cc
+++ b/memory/discardable_memory_shmem.cc
@@ -6,62 +6,17 @@
#include "base/lazy_instance.h"
#include "base/memory/discardable_memory_shmem_allocator.h"
-#include "base/memory/discardable_shared_memory.h"
namespace base {
-namespace {
-
-// Have the DiscardableMemoryManager trigger in-process eviction
-// when address space usage gets too high (e.g. 512 MBytes).
-const size_t kMemoryLimit = 512 * 1024 * 1024;
-
-// internal::DiscardableMemoryManager has an explicit constructor that takes
-// a number of memory limit parameters. The LeakyLazyInstanceTraits doesn't
-// handle the case. Thus, we need our own class here.
-struct DiscardableMemoryManagerLazyInstanceTraits {
- // Leaky as discardable memory clients can use this after the exit handler
- // has been called.
- static const bool kRegisterOnExit = false;
-#ifndef NDEBUG
- static const bool kAllowedToAccessOnNonjoinableThread = true;
-#endif
-
- static internal::DiscardableMemoryManager* New(void* instance) {
- return new (instance) internal::DiscardableMemoryManager(
- kMemoryLimit, kMemoryLimit, TimeDelta::Max());
- }
- static void Delete(internal::DiscardableMemoryManager* instance) {
- instance->~DiscardableMemoryManager();
- }
-};
-
-LazyInstance<internal::DiscardableMemoryManager,
- DiscardableMemoryManagerLazyInstanceTraits> g_manager =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
namespace internal {
DiscardableMemoryShmem::DiscardableMemoryShmem(size_t bytes)
: bytes_(bytes), is_locked_(false) {
- g_manager.Pointer()->Register(this, bytes);
}
DiscardableMemoryShmem::~DiscardableMemoryShmem() {
if (is_locked_)
Unlock();
- g_manager.Pointer()->Unregister(this);
-}
-
-// static
-void DiscardableMemoryShmem::ReleaseFreeMemory() {
- g_manager.Pointer()->ReleaseFreeMemory();
-}
-
-// static
-void DiscardableMemoryShmem::PurgeForTesting() {
- g_manager.Pointer()->PurgeAll();
}
bool DiscardableMemoryShmem::Initialize() {
@@ -71,18 +26,24 @@
DiscardableMemoryLockStatus DiscardableMemoryShmem::Lock() {
DCHECK(!is_locked_);
- bool purged = false;
- if (!g_manager.Pointer()->AcquireLock(this, &purged))
+ if (chunk_ && chunk_->Lock()) {
+ is_locked_ = true;
+ return DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+ }
+
+ chunk_ = DiscardableMemoryShmemAllocator::GetInstance()
+ ->AllocateLockedDiscardableMemory(bytes_);
+ if (!chunk_)
return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
is_locked_ = true;
- return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
- : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+ return DISCARDABLE_MEMORY_LOCK_STATUS_PURGED;
}
void DiscardableMemoryShmem::Unlock() {
DCHECK(is_locked_);
- g_manager.Pointer()->ReleaseLock(this);
+ DCHECK(chunk_);
+ chunk_->Unlock();
is_locked_ = false;
}
@@ -92,28 +53,5 @@
return chunk_->Memory();
}
-bool DiscardableMemoryShmem::AllocateAndAcquireLock() {
- if (chunk_ && chunk_->Lock())
- return true;
-
- chunk_ = DiscardableMemoryShmemAllocator::GetInstance()
- ->AllocateLockedDiscardableMemory(bytes_);
- DCHECK(chunk_);
- return false;
-}
-
-void DiscardableMemoryShmem::ReleaseLock() {
- chunk_->Unlock();
-}
-
-void DiscardableMemoryShmem::Purge() {
- DCHECK(!is_locked_);
- chunk_.reset();
-}
-
-bool DiscardableMemoryShmem::IsMemoryResident() const {
- return chunk_->IsMemoryResident();
-}
-
} // namespace internal
} // namespace base
diff --git a/memory/discardable_memory_shmem.h b/memory/discardable_memory_shmem.h
index b04c9b1..98d3b97 100644
--- a/memory/discardable_memory_shmem.h
+++ b/memory/discardable_memory_shmem.h
@@ -7,24 +7,16 @@
#include "base/memory/discardable_memory.h"
-#include "base/memory/discardable_memory_manager.h"
-
namespace base {
class DiscardableMemoryShmemChunk;
namespace internal {
-class DiscardableMemoryShmem
- : public DiscardableMemory,
- public internal::DiscardableMemoryManagerAllocation {
+class DiscardableMemoryShmem : public DiscardableMemory {
public:
explicit DiscardableMemoryShmem(size_t bytes);
~DiscardableMemoryShmem() override;
- static void ReleaseFreeMemory();
-
- static void PurgeForTesting();
-
bool Initialize();
// Overridden from DiscardableMemory:
@@ -32,12 +24,6 @@
void Unlock() override;
void* Memory() const override;
- // Overridden from internal::DiscardableMemoryManagerAllocation:
- bool AllocateAndAcquireLock() override;
- void ReleaseLock() override;
- void Purge() override;
- bool IsMemoryResident() const override;
-
private:
const size_t bytes_;
scoped_ptr<DiscardableMemoryShmemChunk> chunk_;
diff --git a/memory/discardable_memory_shmem_allocator.cc b/memory/discardable_memory_shmem_allocator.cc
index 8abe456..761204f 100644
--- a/memory/discardable_memory_shmem_allocator.cc
+++ b/memory/discardable_memory_shmem_allocator.cc
@@ -18,16 +18,12 @@
: shared_memory_(shared_memory.Pass()) {}
// Overridden from DiscardableMemoryShmemChunk:
- bool Lock() override {
- auto result = shared_memory_->Lock(0, 0);
- DCHECK_NE(result, DiscardableSharedMemory::PURGED);
- return result == DiscardableSharedMemory::SUCCESS;
+ bool Lock() override { return false; }
+ void Unlock() override {
+ shared_memory_->Unlock(0, 0);
+ shared_memory_.reset();
}
- void Unlock() override { shared_memory_->Unlock(0, 0); }
void* Memory() const override { return shared_memory_->memory(); }
- bool IsMemoryResident() const override {
- return shared_memory_->IsMemoryResident();
- }
private:
scoped_ptr<DiscardableSharedMemory> shared_memory_;
diff --git a/memory/discardable_memory_shmem_allocator.h b/memory/discardable_memory_shmem_allocator.h
index ed40672..ac4118e 100644
--- a/memory/discardable_memory_shmem_allocator.h
+++ b/memory/discardable_memory_shmem_allocator.h
@@ -19,7 +19,6 @@
virtual bool Lock() = 0;
virtual void Unlock() = 0;
virtual void* Memory() const = 0;
- virtual bool IsMemoryResident() const = 0;
};
class BASE_EXPORT DiscardableMemoryShmemAllocator {
diff --git a/memory/discardable_memory_unittest.cc b/memory/discardable_memory_unittest.cc
index 4510413..fb1eba6 100644
--- a/memory/discardable_memory_unittest.cc
+++ b/memory/discardable_memory_unittest.cc
@@ -82,16 +82,6 @@
ASSERT_TRUE(memory);
}
-// Test forced purging.
-TEST_P(DiscardableMemoryTest, Purge) {
- const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize));
- ASSERT_TRUE(memory);
- memory->Unlock();
-
- DiscardableMemory::PurgeForTesting();
- EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, memory->Lock());
-}
-
#if !defined(NDEBUG) && !defined(OS_ANDROID)
// Death tests are not supported with Android APKs.
TEST_P(DiscardableMemoryTest, UnlockedMemoryAccessCrashesInDebugMode) {
diff --git a/memory/discardable_memory_win.cc b/memory/discardable_memory_win.cc
index 9b4e940..977b029 100644
--- a/memory/discardable_memory_win.cc
+++ b/memory/discardable_memory_win.cc
@@ -11,11 +11,6 @@
namespace base {
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -61,10 +56,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/memory/discardable_shared_memory.cc b/memory/discardable_shared_memory.cc
index 3805bed..49e93cd 100644
--- a/memory/discardable_shared_memory.cc
+++ b/memory/discardable_shared_memory.cc
@@ -162,19 +162,19 @@
DCHECK_EQ(AlignToPageSize(offset), offset);
DCHECK_EQ(AlignToPageSize(length), length);
- // Calls to this function must synchronized properly.
+ // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_);
- // Return false when instance has been purged or not initialized properly by
- // checking if |last_known_usage_| is NULL.
- if (last_known_usage_.is_null())
- return FAILED;
-
DCHECK(shared_memory_.memory());
// We need to successfully acquire the platform independent lock before
// individual pages can be locked.
if (!locked_page_count_) {
+ // Return false when instance has been purged or not initialized properly
+ // by checking if |last_known_usage_| is NULL.
+ if (last_known_usage_.is_null())
+ return FAILED;
+
SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
SharedState new_state(SharedState::LOCKED, Time());
SharedState result(subtle::Acquire_CompareAndSwap(
@@ -226,7 +226,7 @@
DCHECK_EQ(AlignToPageSize(offset), offset);
DCHECK_EQ(AlignToPageSize(length), length);
- // Calls to this function must synchronized properly.
+ // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_);
// Zero for length means "everything onward".
@@ -294,7 +294,7 @@
}
bool DiscardableSharedMemory::Purge(Time current_time) {
- // Calls to this function must synchronized properly.
+ // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_);
// Early out if not mapped. This can happen if the segment was previously
diff --git a/memory/discardable_shared_memory_unittest.cc b/memory/discardable_shared_memory_unittest.cc
index 1f08aea..74d19a6 100644
--- a/memory/discardable_shared_memory_unittest.cc
+++ b/memory/discardable_shared_memory_unittest.cc
@@ -234,8 +234,6 @@
// Lock should fail as memory has been purged.
auto lock_rv = memory2.Lock(0, 0);
EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
- lock_rv = memory1.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
}
TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) {
@@ -263,27 +261,39 @@
rv = memory1.Purge(Time::FromDoubleT(2));
EXPECT_FALSE(rv);
- // Unlock second page.
+ // Lock first page again.
memory2.SetNow(Time::FromDoubleT(3));
+ auto lock_rv = memory2.Lock(0, base::GetPageSize());
+ EXPECT_NE(DiscardableSharedMemory::FAILED, lock_rv);
+
+ // Unlock first page.
+ memory2.SetNow(Time::FromDoubleT(4));
+ memory2.Unlock(0, base::GetPageSize());
+
+ rv = memory1.Purge(Time::FromDoubleT(5));
+ EXPECT_FALSE(rv);
+
+ // Unlock second page.
+ memory2.SetNow(Time::FromDoubleT(6));
memory2.Unlock(base::GetPageSize(), base::GetPageSize());
- rv = memory1.Purge(Time::FromDoubleT(4));
+ rv = memory1.Purge(Time::FromDoubleT(7));
EXPECT_FALSE(rv);
// Unlock anything onwards.
- memory2.SetNow(Time::FromDoubleT(5));
+ memory2.SetNow(Time::FromDoubleT(8));
memory2.Unlock(2 * base::GetPageSize(), 0);
// Memory is unlocked, but our usage timestamp is incorrect.
- rv = memory1.Purge(Time::FromDoubleT(6));
+ rv = memory1.Purge(Time::FromDoubleT(9));
EXPECT_FALSE(rv);
// The failed purge attempt should have updated usage time to the correct
// value.
- EXPECT_EQ(Time::FromDoubleT(5), memory1.last_known_usage());
+ EXPECT_EQ(Time::FromDoubleT(8), memory1.last_known_usage());
// Purge should now succeed.
- rv = memory1.Purge(Time::FromDoubleT(7));
+ rv = memory1.Purge(Time::FromDoubleT(10));
EXPECT_TRUE(rv);
}
diff --git a/memory/memory_pressure_listener.cc b/memory/memory_pressure_listener.cc
index d808502..6a8ed21 100644
--- a/memory/memory_pressure_listener.cc
+++ b/memory/memory_pressure_listener.cc
@@ -54,7 +54,7 @@
DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE);
TRACE_EVENT1("memory", "MemoryPressureListener::NotifyMemoryPressure",
"level", memory_pressure_level);
- g_observers.Get().Notify(&MemoryPressureListener::Notify,
+ g_observers.Get().Notify(FROM_HERE, &MemoryPressureListener::Notify,
memory_pressure_level);
}
diff --git a/memory/scoped_ptr.h b/memory/scoped_ptr.h
index ae9eb0f..987ccfa 100644
--- a/memory/scoped_ptr.h
+++ b/memory/scoped_ptr.h
@@ -85,6 +85,7 @@
#include <stdlib.h>
#include <algorithm> // For std::swap().
+#include <iosfwd>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
@@ -585,4 +586,9 @@
return scoped_ptr<T>(ptr);
}
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
+ return out << p.get();
+}
+
#endif // BASE_MEMORY_SCOPED_PTR_H_
diff --git a/memory/scoped_ptr_unittest.cc b/memory/scoped_ptr_unittest.cc
index ca7cfbf..0887a99 100644
--- a/memory/scoped_ptr_unittest.cc
+++ b/memory/scoped_ptr_unittest.cc
@@ -4,9 +4,12 @@
#include "base/memory/scoped_ptr.h"
+#include <sstream>
+
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
+#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -678,3 +681,13 @@
scoped_ptr<int, NoOpDeleter> x(owner.get());
x.reset(x.get());
}
+
+// Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean
+// value first.
+TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) {
+ scoped_ptr<int> x(new int);
+ std::stringstream s;
+ s << x;
+ std::string expected = base::StringPrintf("%p", x.get());
+ EXPECT_EQ(expected, s.str());
+}
diff --git a/message_loop/message_loop.cc b/message_loop/message_loop.cc
index 86771e4..daa7782 100644
--- a/message_loop/message_loop.cc
+++ b/message_loop/message_loop.cc
@@ -152,7 +152,12 @@
MessageLoop::~MessageLoop() {
DCHECK_EQ(this, current());
+ // iOS just attaches to the loop, it doesn't Run it.
+ // TODO(stuartmorgan): Consider wiring up a Detach().
+#if !defined(OS_IOS)
DCHECK(!run_loop_);
+#endif
+
#if defined(OS_WIN)
if (in_high_res_mode_)
Time::ActivateHighResolutionTimer(false);
diff --git a/metrics/field_trial.cc b/metrics/field_trial.cc
index e03c94c..639f6d3 100644
--- a/metrics/field_trial.cc
+++ b/metrics/field_trial.cc
@@ -547,9 +547,8 @@
return;
global_->observer_list_->Notify(
- &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
- field_trial->trial_name(),
- field_trial->group_name_internal());
+ FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
+ field_trial->trial_name(), field_trial->group_name_internal());
}
// static
diff --git a/metrics/histogram_macros.h b/metrics/histogram_macros.h
index e9a871c..2aee1a5 100644
--- a/metrics/histogram_macros.h
+++ b/metrics/histogram_macros.h
@@ -229,4 +229,36 @@
base::CustomHistogram::FactoryGet(name, custom_ranges, \
base::HistogramBase::kUmaTargetedHistogramFlag))
+// Scoped class which logs its time on this earth as a UMA statistic. This is
+// recommended for when you want a histogram which measures the time it takes
+// for a method to execute. This measures up to 10 seconds.
+#define SCOPED_UMA_HISTOGRAM_TIMER(name) \
+ SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, false, __COUNTER__)
+
+// Similar scoped histogram timer, but this uses UMA_HISTOGRAM_LONG_TIMES_100,
+// which measures up to an hour, and uses 100 buckets. This is more expensive
+// to store, so only use if this often takes >10 seconds.
+#define SCOPED_UMA_HISTOGRAM_LONG_TIMER(name) \
+ SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, true, __COUNTER__)
+
+// This nested macro is necessary to expand __COUNTER__ to an actual value.
+#define SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
+ SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
+
+#define SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
+ class ScopedHistogramTimer##key { \
+ public: \
+ ScopedHistogramTimer##key() : constructed_(base::TimeTicks::Now()) {} \
+ ~ScopedHistogramTimer##key() { \
+ base::TimeDelta elapsed = base::TimeTicks::Now() - constructed_; \
+ if (is_long) { \
+ UMA_HISTOGRAM_LONG_TIMES_100(name, elapsed); \
+ } else { \
+ UMA_HISTOGRAM_TIMES(name, elapsed); \
+ } \
+ } \
+ private: \
+ base::TimeTicks constructed_; \
+ } scoped_histogram_timer_##key
+
#endif // BASE_METRICS_HISTOGRAM_MACROS_H_
diff --git a/metrics/histogram_macros_unittest.cc b/metrics/histogram_macros_unittest.cc
new file mode 100644
index 0000000..c599161
--- /dev/null
+++ b/metrics/histogram_macros_unittest.cc
@@ -0,0 +1,18 @@
+// Copyright 2015 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/metrics/histogram_macros.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+TEST(ScopedHistogramTimer, TwoTimersOneScope) {
+ SCOPED_UMA_HISTOGRAM_TIMER("TestTimer0");
+ SCOPED_UMA_HISTOGRAM_TIMER("TestTimer1");
+ SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer0");
+ SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer1");
+}
+
+} // namespace base
diff --git a/metrics/stats_counters.cc b/metrics/stats_counters.cc
deleted file mode 100644
index 12416d9..0000000
--- a/metrics/stats_counters.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2010 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/metrics/stats_counters.h"
-
-namespace base {
-
-StatsCounter::StatsCounter(const std::string& name)
- : counter_id_(-1) {
- // We prepend the name with 'c:' to indicate that it is a counter.
- if (StatsTable::current()) {
- // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
- // static.
- name_ = "c:";
- name_.append(name);
- }
-}
-
-StatsCounter::~StatsCounter() {
-}
-
-void StatsCounter::Set(int value) {
- int* loc = GetPtr();
- if (loc)
- *loc = value;
-}
-
-void StatsCounter::Add(int value) {
- int* loc = GetPtr();
- if (loc)
- (*loc) += value;
-}
-
-StatsCounter::StatsCounter()
- : counter_id_(-1) {
-}
-
-int* StatsCounter::GetPtr() {
- StatsTable* table = StatsTable::current();
- if (!table)
- return NULL;
-
- // If counter_id_ is -1, then we haven't looked it up yet.
- if (counter_id_ == -1) {
- counter_id_ = table->FindCounter(name_);
- if (table->GetSlot() == 0) {
- if (!table->RegisterThread(std::string())) {
- // There is no room for this thread. This thread
- // cannot use counters.
- counter_id_ = 0;
- return NULL;
- }
- }
- }
-
- // If counter_id_ is > 0, then we have a valid counter.
- if (counter_id_ > 0)
- return table->GetLocation(counter_id_, table->GetSlot());
-
- // counter_id_ was zero, which means the table is full.
- return NULL;
-}
-
-
-StatsCounterTimer::StatsCounterTimer(const std::string& name) {
- // we prepend the name with 't:' to indicate that it is a timer.
- if (StatsTable::current()) {
- // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
- // static.
- name_ = "t:";
- name_.append(name);
- }
-}
-
-StatsCounterTimer::~StatsCounterTimer() {
-}
-
-void StatsCounterTimer::Start() {
- if (!Enabled())
- return;
- start_time_ = TimeTicks::Now();
- stop_time_ = TimeTicks();
-}
-
-// Stop the timer and record the results.
-void StatsCounterTimer::Stop() {
- if (!Enabled() || !Running())
- return;
- stop_time_ = TimeTicks::Now();
- Record();
-}
-
-// Returns true if the timer is running.
-bool StatsCounterTimer::Running() {
- return Enabled() && !start_time_.is_null() && stop_time_.is_null();
-}
-
-// Accept a TimeDelta to increment.
-void StatsCounterTimer::AddTime(TimeDelta time) {
- Add(static_cast<int>(time.InMilliseconds()));
-}
-
-void StatsCounterTimer::Record() {
- AddTime(stop_time_ - start_time_);
-}
-
-
-StatsRate::StatsRate(const std::string& name)
- : StatsCounterTimer(name),
- counter_(name),
- largest_add_(std::string(" ").append(name).append("MAX")) {
-}
-
-StatsRate::~StatsRate() {
-}
-
-void StatsRate::Add(int value) {
- counter_.Increment();
- StatsCounterTimer::Add(value);
- if (value > largest_add_.value())
- largest_add_.Set(value);
-}
-
-} // namespace base
diff --git a/metrics/stats_counters.h b/metrics/stats_counters.h
deleted file mode 100644
index 0f8354f..0000000
--- a/metrics/stats_counters.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright (c) 2011 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 BASE_METRICS_STATS_COUNTERS_H_
-#define BASE_METRICS_STATS_COUNTERS_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/compiler_specific.h"
-#include "base/metrics/stats_table.h"
-#include "base/time/time.h"
-
-namespace base {
-
-// StatsCounters are dynamically created values which can be tracked in
-// the StatsTable. They are designed to be lightweight to create and
-// easy to use.
-//
-// Since StatsCounters can be created dynamically by name, there is
-// a hash table lookup to find the counter in the table. A StatsCounter
-// object can be created once and used across multiple threads safely.
-//
-// Example usage:
-// {
-// StatsCounter request_count("RequestCount");
-// request_count.Increment();
-// }
-//
-// Note that creating counters on the stack does work, however creating
-// the counter object requires a hash table lookup. For inner loops, it
-// may be better to create the counter either as a member of another object
-// (or otherwise outside of the loop) for maximum performance.
-//
-// Internally, a counter represents a value in a row of a StatsTable.
-// The row has a 32bit value for each process/thread in the table and also
-// a name (stored in the table metadata).
-//
-// NOTE: In order to make stats_counters usable in lots of different code,
-// avoid any dependencies inside this header file.
-//
-
-//------------------------------------------------------------------------------
-// Define macros for ease of use. They also allow us to change definitions
-// as the implementation varies, or depending on compile options.
-//------------------------------------------------------------------------------
-// First provide generic macros, which exist in production as well as debug.
-#define STATS_COUNTER(name, delta) do { \
- base::StatsCounter counter(name); \
- counter.Add(delta); \
-} while (0)
-
-#define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1)
-
-#define RATE_COUNTER(name, duration) do { \
- base::StatsRate hit_count(name); \
- hit_count.AddTime(duration); \
-} while (0)
-
-// Define Debug vs non-debug flavors of macros.
-#ifndef NDEBUG
-
-#define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta)
-#define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name)
-#define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration)
-
-#else // NDEBUG
-
-#define DSTATS_COUNTER(name, delta) do {} while (0)
-#define DSIMPLE_STATS_COUNTER(name) do {} while (0)
-#define DRATE_COUNTER(name, duration) do {} while (0)
-
-#endif // NDEBUG
-
-//------------------------------------------------------------------------------
-// StatsCounter represents a counter in the StatsTable class.
-class BASE_EXPORT StatsCounter {
- public:
- // Create a StatsCounter object.
- explicit StatsCounter(const std::string& name);
- virtual ~StatsCounter();
-
- // Sets the counter to a specific value.
- void Set(int value);
-
- // Increments the counter.
- void Increment() {
- Add(1);
- }
-
- virtual void Add(int value);
-
- // Decrements the counter.
- void Decrement() {
- Add(-1);
- }
-
- void Subtract(int value) {
- Add(-value);
- }
-
- // Is this counter enabled?
- // Returns false if table is full.
- bool Enabled() {
- return GetPtr() != NULL;
- }
-
- int value() {
- int* loc = GetPtr();
- if (loc) return *loc;
- return 0;
- }
-
- protected:
- StatsCounter();
-
- // Returns the cached address of this counter location.
- int* GetPtr();
-
- std::string name_;
- // The counter id in the table. We initialize to -1 (an invalid value)
- // and then cache it once it has been looked up. The counter_id is
- // valid across all threads and processes.
- int32 counter_id_;
-};
-
-
-// A StatsCounterTimer is a StatsCounter which keeps a timer during
-// the scope of the StatsCounterTimer. On destruction, it will record
-// its time measurement.
-class BASE_EXPORT StatsCounterTimer : protected StatsCounter {
- public:
- // Constructs and starts the timer.
- explicit StatsCounterTimer(const std::string& name);
- ~StatsCounterTimer() override;
-
- // Start the timer.
- void Start();
-
- // Stop the timer and record the results.
- void Stop();
-
- // Returns true if the timer is running.
- bool Running();
-
- // Accept a TimeDelta to increment.
- virtual void AddTime(TimeDelta time);
-
- protected:
- // Compute the delta between start and stop, in milliseconds.
- void Record();
-
- TimeTicks start_time_;
- TimeTicks stop_time_;
-};
-
-// A StatsRate is a timer that keeps a count of the number of intervals added so
-// that several statistics can be produced:
-// min, max, avg, count, total
-class BASE_EXPORT StatsRate : public StatsCounterTimer {
- public:
- // Constructs and starts the timer.
- explicit StatsRate(const std::string& name);
- ~StatsRate() override;
-
- void Add(int value) override;
-
- private:
- StatsCounter counter_;
- StatsCounter largest_add_;
-};
-
-
-// Helper class for scoping a timer or rate.
-template<class T> class StatsScope {
- public:
- explicit StatsScope<T>(T& timer)
- : timer_(timer) {
- timer_.Start();
- }
-
- ~StatsScope() {
- timer_.Stop();
- }
-
- void Stop() {
- timer_.Stop();
- }
-
- private:
- T& timer_;
-};
-
-} // namespace base
-
-#endif // BASE_METRICS_STATS_COUNTERS_H_
diff --git a/metrics/stats_table.cc b/metrics/stats_table.cc
deleted file mode 100644
index 0986395..0000000
--- a/metrics/stats_table.cc
+++ /dev/null
@@ -1,617 +0,0 @@
-// Copyright (c) 2011 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/metrics/stats_table.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/shared_memory.h"
-#include "base/process/process_handle.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local_storage.h"
-
-namespace base {
-
-// The StatsTable uses a shared memory segment that is laid out as follows
-//
-// +-------------------------------------------+
-// | Version | Size | MaxCounters | MaxThreads |
-// +-------------------------------------------+
-// | Thread names table |
-// +-------------------------------------------+
-// | Thread TID table |
-// +-------------------------------------------+
-// | Thread PID table |
-// +-------------------------------------------+
-// | Counter names table |
-// +-------------------------------------------+
-// | Data |
-// +-------------------------------------------+
-//
-// The data layout is a grid, where the columns are the thread_ids and the
-// rows are the counter_ids.
-//
-// If the first character of the thread_name is '\0', then that column is
-// empty.
-// If the first character of the counter_name is '\0', then that row is
-// empty.
-//
-// About Locking:
-// This class is designed to be both multi-thread and multi-process safe.
-// Aside from initialization, this is done by partitioning the data which
-// each thread uses so that no locking is required. However, to allocate
-// the rows and columns of the table to particular threads, locking is
-// required.
-//
-// At the shared-memory level, we have a lock. This lock protects the
-// shared-memory table only, and is used when we create new counters (e.g.
-// use rows) or when we register new threads (e.g. use columns). Reading
-// data from the table does not require any locking at the shared memory
-// level.
-//
-// Each process which accesses the table will create a StatsTable object.
-// The StatsTable maintains a hash table of the existing counters in the
-// table for faster lookup. Since the hash table is process specific,
-// each process maintains its own cache. We avoid complexity here by never
-// de-allocating from the hash table. (Counters are dynamically added,
-// but not dynamically removed).
-
-// In order for external viewers to be able to read our shared memory,
-// we all need to use the same size ints.
-COMPILE_ASSERT(sizeof(int)==4, expect_4_byte_ints);
-
-namespace {
-
-// An internal version in case we ever change the format of this
-// file, and so that we can identify our table.
-const int kTableVersion = 0x13131313;
-
-// The name for un-named counters and threads in the table.
-const char kUnknownName[] = "<unknown>";
-
-// Calculates delta to align an offset to the size of an int
-inline int AlignOffset(int offset) {
- return (sizeof(int) - (offset % sizeof(int))) % sizeof(int);
-}
-
-inline int AlignedSize(int size) {
- return size + AlignOffset(size);
-}
-
-} // namespace
-
-// The StatsTable::Internal maintains convenience pointers into the
-// shared memory segment. Use this class to keep the data structure
-// clean and accessible.
-class StatsTable::Internal {
- public:
- // Various header information contained in the memory mapped segment.
- struct TableHeader {
- int version;
- int size;
- int max_counters;
- int max_threads;
- };
-
- // Construct a new Internal based on expected size parameters, or
- // return NULL on failure.
- static Internal* New(const StatsTable::TableIdentifier& table,
- int size,
- int max_threads,
- int max_counters);
-
- SharedMemory* shared_memory() { return shared_memory_.get(); }
-
- // Accessors for our header pointers
- TableHeader* table_header() const { return table_header_; }
- int version() const { return table_header_->version; }
- int size() const { return table_header_->size; }
- int max_counters() const { return table_header_->max_counters; }
- int max_threads() const { return table_header_->max_threads; }
-
- // Accessors for our tables
- char* thread_name(int slot_id) const {
- return &thread_names_table_[
- (slot_id-1) * (StatsTable::kMaxThreadNameLength)];
- }
- PlatformThreadId* thread_tid(int slot_id) const {
- return &(thread_tid_table_[slot_id-1]);
- }
- int* thread_pid(int slot_id) const {
- return &(thread_pid_table_[slot_id-1]);
- }
- char* counter_name(int counter_id) const {
- return &counter_names_table_[
- (counter_id-1) * (StatsTable::kMaxCounterNameLength)];
- }
- int* row(int counter_id) const {
- return &data_table_[(counter_id-1) * max_threads()];
- }
-
- private:
- // Constructor is private because you should use New() instead.
- explicit Internal(SharedMemory* shared_memory)
- : shared_memory_(shared_memory),
- table_header_(NULL),
- thread_names_table_(NULL),
- thread_tid_table_(NULL),
- thread_pid_table_(NULL),
- counter_names_table_(NULL),
- data_table_(NULL) {
- }
-
- // Create or open the SharedMemory used by the stats table.
- static SharedMemory* CreateSharedMemory(
- const StatsTable::TableIdentifier& table,
- int size);
-
- // Initializes the table on first access. Sets header values
- // appropriately and zeroes all counters.
- void InitializeTable(void* memory, int size, int max_counters,
- int max_threads);
-
- // Initializes our in-memory pointers into a pre-created StatsTable.
- void ComputeMappedPointers(void* memory);
-
- scoped_ptr<SharedMemory> shared_memory_;
- TableHeader* table_header_;
- char* thread_names_table_;
- PlatformThreadId* thread_tid_table_;
- int* thread_pid_table_;
- char* counter_names_table_;
- int* data_table_;
-
- DISALLOW_COPY_AND_ASSIGN(Internal);
-};
-
-// static
-StatsTable::Internal* StatsTable::Internal::New(
- const StatsTable::TableIdentifier& table,
- int size,
- int max_threads,
- int max_counters) {
- scoped_ptr<SharedMemory> shared_memory(CreateSharedMemory(table, size));
- if (!shared_memory.get())
- return NULL;
- if (!shared_memory->Map(size))
- return NULL;
- void* memory = shared_memory->memory();
-
- scoped_ptr<Internal> internal(new Internal(shared_memory.release()));
- TableHeader* header = static_cast<TableHeader*>(memory);
-
- // If the version does not match, then assume the table needs
- // to be initialized.
- if (header->version != kTableVersion)
- internal->InitializeTable(memory, size, max_counters, max_threads);
-
- // We have a valid table, so compute our pointers.
- internal->ComputeMappedPointers(memory);
-
- return internal.release();
-}
-
-// static
-SharedMemory* StatsTable::Internal::CreateSharedMemory(
- const StatsTable::TableIdentifier& table,
- int size) {
-#if defined(OS_POSIX)
- // Check for existing table.
- if (table.fd != -1)
- return new SharedMemory(table, false);
-
- // Otherwise we need to create it.
- scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
- if (!shared_memory->CreateAnonymous(size))
- return NULL;
- return shared_memory.release();
-#elif defined(OS_WIN)
- scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
- if (table.empty()) {
- // Create an anonymous table.
- if (!shared_memory->CreateAnonymous(size))
- return NULL;
- } else {
- // Create a named table for sharing between processes.
- if (!shared_memory->CreateNamedDeprecated(table, true, size))
- return NULL;
- }
- return shared_memory.release();
-#endif
-}
-
-void StatsTable::Internal::InitializeTable(void* memory, int size,
- int max_counters,
- int max_threads) {
- // Zero everything.
- memset(memory, 0, size);
-
- // Initialize the header.
- TableHeader* header = static_cast<TableHeader*>(memory);
- header->version = kTableVersion;
- header->size = size;
- header->max_counters = max_counters;
- header->max_threads = max_threads;
-}
-
-void StatsTable::Internal::ComputeMappedPointers(void* memory) {
- char* data = static_cast<char*>(memory);
- int offset = 0;
-
- table_header_ = reinterpret_cast<TableHeader*>(data);
- offset += sizeof(*table_header_);
- offset += AlignOffset(offset);
-
- // Verify we're looking at a valid StatsTable.
- DCHECK_EQ(table_header_->version, kTableVersion);
-
- thread_names_table_ = reinterpret_cast<char*>(data + offset);
- offset += sizeof(char) *
- max_threads() * StatsTable::kMaxThreadNameLength;
- offset += AlignOffset(offset);
-
- thread_tid_table_ = reinterpret_cast<PlatformThreadId*>(data + offset);
- offset += sizeof(int) * max_threads();
- offset += AlignOffset(offset);
-
- thread_pid_table_ = reinterpret_cast<int*>(data + offset);
- offset += sizeof(int) * max_threads();
- offset += AlignOffset(offset);
-
- counter_names_table_ = reinterpret_cast<char*>(data + offset);
- offset += sizeof(char) *
- max_counters() * StatsTable::kMaxCounterNameLength;
- offset += AlignOffset(offset);
-
- data_table_ = reinterpret_cast<int*>(data + offset);
- offset += sizeof(int) * max_threads() * max_counters();
-
- DCHECK_EQ(offset, size());
-}
-
-// TLSData carries the data stored in the TLS slots for the
-// StatsTable. This is used so that we can properly cleanup when the
-// thread exits and return the table slot.
-//
-// Each thread that calls RegisterThread in the StatsTable will have
-// a TLSData stored in its TLS.
-struct StatsTable::TLSData {
- StatsTable* table;
- int slot;
-};
-
-// We keep a singleton table which can be easily accessed.
-StatsTable* global_table = NULL;
-
-StatsTable::StatsTable(const TableIdentifier& table,
- int max_threads,
- int max_counters)
- : internal_(NULL),
- tls_index_(SlotReturnFunction) {
- int table_size =
- AlignedSize(sizeof(Internal::TableHeader)) +
- AlignedSize((max_counters * sizeof(char) * kMaxCounterNameLength)) +
- AlignedSize((max_threads * sizeof(char) * kMaxThreadNameLength)) +
- AlignedSize(max_threads * sizeof(int)) +
- AlignedSize(max_threads * sizeof(int)) +
- AlignedSize((sizeof(int) * (max_counters * max_threads)));
-
- internal_ = Internal::New(table, table_size, max_threads, max_counters);
-
- if (!internal_)
- DPLOG(ERROR) << "StatsTable did not initialize";
-}
-
-StatsTable::~StatsTable() {
- // Before we tear down our copy of the table, be sure to
- // unregister our thread.
- UnregisterThread();
-
- // Return ThreadLocalStorage. At this point, if any registered threads
- // still exist, they cannot Unregister.
- tls_index_.Free();
-
- // Cleanup our shared memory.
- delete internal_;
-
- // If we are the global table, unregister ourselves.
- if (global_table == this)
- global_table = NULL;
-}
-
-StatsTable* StatsTable::current() {
- return global_table;
-}
-
-void StatsTable::set_current(StatsTable* value) {
- global_table = value;
-}
-
-int StatsTable::GetSlot() const {
- TLSData* data = GetTLSData();
- if (!data)
- return 0;
- return data->slot;
-}
-
-int StatsTable::RegisterThread(const std::string& name) {
- int slot = 0;
- if (!internal_)
- return 0;
-
- // Registering a thread requires that we lock the shared memory
- // so that two threads don't grab the same slot. Fortunately,
- // thread creation shouldn't happen in inner loops.
- // TODO(viettrungluu): crbug.com/345734: Use a different locking mechanism.
- {
- SharedMemoryAutoLockDeprecated lock(internal_->shared_memory());
- slot = FindEmptyThread();
- if (!slot) {
- return 0;
- }
-
- // We have space, so consume a column in the table.
- std::string thread_name = name;
- if (name.empty())
- thread_name = kUnknownName;
- strlcpy(internal_->thread_name(slot), thread_name.c_str(),
- kMaxThreadNameLength);
- *(internal_->thread_tid(slot)) = PlatformThread::CurrentId();
- *(internal_->thread_pid(slot)) = GetCurrentProcId();
- }
-
- // Set our thread local storage.
- TLSData* data = new TLSData;
- data->table = this;
- data->slot = slot;
- tls_index_.Set(data);
- return slot;
-}
-
-int StatsTable::CountThreadsRegistered() const {
- if (!internal_)
- return 0;
-
- // Loop through the shared memory and count the threads that are active.
- // We intentionally do not lock the table during the operation.
- int count = 0;
- for (int index = 1; index <= internal_->max_threads(); index++) {
- char* name = internal_->thread_name(index);
- if (*name != '\0')
- count++;
- }
- return count;
-}
-
-int StatsTable::FindCounter(const std::string& name) {
- // Note: the API returns counters numbered from 1..N, although
- // internally, the array is 0..N-1. This is so that we can return
- // zero as "not found".
- if (!internal_)
- return 0;
-
- // Create a scope for our auto-lock.
- {
- AutoLock scoped_lock(counters_lock_);
-
- // Attempt to find the counter.
- CountersMap::const_iterator iter;
- iter = counters_.find(name);
- if (iter != counters_.end())
- return iter->second;
- }
-
- // Counter does not exist, so add it.
- return AddCounter(name);
-}
-
-int* StatsTable::GetLocation(int counter_id, int slot_id) const {
- if (!internal_)
- return NULL;
- if (slot_id > internal_->max_threads())
- return NULL;
-
- int* row = internal_->row(counter_id);
- return &(row[slot_id-1]);
-}
-
-const char* StatsTable::GetRowName(int index) const {
- if (!internal_)
- return NULL;
-
- return internal_->counter_name(index);
-}
-
-int StatsTable::GetRowValue(int index) const {
- return GetRowValue(index, 0);
-}
-
-int StatsTable::GetRowValue(int index, int pid) const {
- if (!internal_)
- return 0;
-
- int rv = 0;
- int* row = internal_->row(index);
- for (int slot_id = 1; slot_id <= internal_->max_threads(); slot_id++) {
- if (pid == 0 || *internal_->thread_pid(slot_id) == pid)
- rv += row[slot_id-1];
- }
- return rv;
-}
-
-int StatsTable::GetCounterValue(const std::string& name) {
- return GetCounterValue(name, 0);
-}
-
-int StatsTable::GetCounterValue(const std::string& name, int pid) {
- if (!internal_)
- return 0;
-
- int row = FindCounter(name);
- if (!row)
- return 0;
- return GetRowValue(row, pid);
-}
-
-int StatsTable::GetMaxCounters() const {
- if (!internal_)
- return 0;
- return internal_->max_counters();
-}
-
-int StatsTable::GetMaxThreads() const {
- if (!internal_)
- return 0;
- return internal_->max_threads();
-}
-
-int* StatsTable::FindLocation(const char* name) {
- // Get the static StatsTable
- StatsTable *table = StatsTable::current();
- if (!table)
- return NULL;
-
- // Get the slot for this thread. Try to register
- // it if none exists.
- int slot = table->GetSlot();
- if (!slot)
- slot = table->RegisterThread(std::string());
- if (!slot)
- return NULL;
-
- // Find the counter id for the counter.
- std::string str_name(name);
- int counter = table->FindCounter(str_name);
-
- // Now we can find the location in the table.
- return table->GetLocation(counter, slot);
-}
-
-void StatsTable::UnregisterThread() {
- UnregisterThread(GetTLSData());
-}
-
-void StatsTable::UnregisterThread(TLSData* data) {
- if (!data)
- return;
- DCHECK(internal_);
-
- // Mark the slot free by zeroing out the thread name.
- char* name = internal_->thread_name(data->slot);
- *name = '\0';
-
- // Remove the calling thread's TLS so that it cannot use the slot.
- tls_index_.Set(NULL);
- delete data;
-}
-
-void StatsTable::SlotReturnFunction(void* data) {
- // This is called by the TLS destructor, which on some platforms has
- // already cleared the TLS info, so use the tls_data argument
- // rather than trying to fetch it ourselves.
- TLSData* tls_data = static_cast<TLSData*>(data);
- if (tls_data) {
- DCHECK(tls_data->table);
- tls_data->table->UnregisterThread(tls_data);
- }
-}
-
-int StatsTable::FindEmptyThread() const {
- // Note: the API returns slots numbered from 1..N, although
- // internally, the array is 0..N-1. This is so that we can return
- // zero as "not found".
- //
- // The reason for doing this is because the thread 'slot' is stored
- // in TLS, which is always initialized to zero, not -1. If 0 were
- // returned as a valid slot number, it would be confused with the
- // uninitialized state.
- if (!internal_)
- return 0;
-
- int index = 1;
- for (; index <= internal_->max_threads(); index++) {
- char* name = internal_->thread_name(index);
- if (!*name)
- break;
- }
- if (index > internal_->max_threads())
- return 0; // The table is full.
- return index;
-}
-
-int StatsTable::FindCounterOrEmptyRow(const std::string& name) const {
- // Note: the API returns slots numbered from 1..N, although
- // internally, the array is 0..N-1. This is so that we can return
- // zero as "not found".
- //
- // There isn't much reason for this other than to be consistent
- // with the way we track columns for thread slots. (See comments
- // in FindEmptyThread for why it is done this way).
- if (!internal_)
- return 0;
-
- int free_slot = 0;
- for (int index = 1; index <= internal_->max_counters(); index++) {
- char* row_name = internal_->counter_name(index);
- if (!*row_name && !free_slot)
- free_slot = index; // save that we found a free slot
- else if (!strncmp(row_name, name.c_str(), kMaxCounterNameLength))
- return index;
- }
- return free_slot;
-}
-
-int StatsTable::AddCounter(const std::string& name) {
- if (!internal_)
- return 0;
-
- int counter_id = 0;
- {
- // To add a counter to the shared memory, we need the
- // shared memory lock.
- SharedMemoryAutoLockDeprecated lock(internal_->shared_memory());
-
- // We have space, so create a new counter.
- counter_id = FindCounterOrEmptyRow(name);
- if (!counter_id)
- return 0;
-
- std::string counter_name = name;
- if (name.empty())
- counter_name = kUnknownName;
- strlcpy(internal_->counter_name(counter_id), counter_name.c_str(),
- kMaxCounterNameLength);
- }
-
- // now add to our in-memory cache
- {
- AutoLock lock(counters_lock_);
- counters_[name] = counter_id;
- }
- return counter_id;
-}
-
-StatsTable::TLSData* StatsTable::GetTLSData() const {
- TLSData* data =
- static_cast<TLSData*>(tls_index_.Get());
- if (!data)
- return NULL;
-
- DCHECK(data->slot);
- DCHECK_EQ(data->table, this);
- return data;
-}
-
-#if defined(OS_POSIX)
-SharedMemoryHandle StatsTable::GetSharedMemoryHandle() const {
- if (!internal_)
- return SharedMemory::NULLHandle();
- return internal_->shared_memory()->handle();
-}
-#endif
-
-} // namespace base
diff --git a/metrics/stats_table.h b/metrics/stats_table.h
deleted file mode 100644
index 719e630..0000000
--- a/metrics/stats_table.h
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2011 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 StatsTable is a table of statistics. It can be used across multiple
-// processes and threads, maintaining cheap statistics counters without
-// locking.
-//
-// The goal is to make it very cheap and easy for developers to add
-// counters to code, without having to build one-off utilities or mechanisms
-// to track the counters, and also to allow a single "view" to display
-// the contents of all counters.
-//
-// To achieve this, StatsTable creates a shared memory segment to store
-// the data for the counters. Upon creation, it has a specific size
-// which governs the maximum number of counters and concurrent
-// threads/processes which can use it.
-//
-
-#ifndef BASE_METRICS_STATS_TABLE_H_
-#define BASE_METRICS_STATS_TABLE_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#include "base/memory/shared_memory.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_local_storage.h"
-#include "build/build_config.h"
-
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#endif
-
-namespace base {
-
-class BASE_EXPORT StatsTable {
- public:
- // Identifies a StatsTable. We often want to share these between processes.
- //
- // On Windows, we use a named shared memory segment so the table identifier
- // should be a relatively unique string identifying the table to use. An
- // empty string can be used to use an anonymous shared memory segment for
- // cases where the table does not need to be shared between processes.
- //
- // Posix does not support named memory so we explicitly share file
- // descriptors. On Posix, pass a default-constructed file descriptor if a
- // handle doesn't already exist, and a new one will be created.
- //
- // If a table doesn't already exist with the given identifier, a new one will
- // be created with zeroed counters.
-#if defined(OS_POSIX)
- typedef FileDescriptor TableIdentifier;
-#elif defined(OS_WIN)
- typedef std::string TableIdentifier;
-#endif
-
- // Create a new StatsTable.
- //
- // max_threads is the maximum number of threads the table will support.
- // If the StatsTable already exists, this number is ignored.
- //
- // max_counters is the maximum number of counters the table will support.
- // If the StatsTable already exists, this number is ignored.
- StatsTable(const TableIdentifier& table,
- int max_threads,
- int max_counters);
-
- // Destroys the StatsTable. When the last StatsTable is destroyed
- // (across all processes), the StatsTable is removed from disk.
- ~StatsTable();
-
- // For convenience, we create a static table. This is generally
- // used automatically by the counters.
- static StatsTable* current();
-
- // Set the global table for use in this process.
- static void set_current(StatsTable* value);
-
- // Get the slot id for the calling thread. Returns 0 if no
- // slot is assigned.
- int GetSlot() const;
-
- // All threads that contribute data to the table must register with the
- // table first. This function will set thread local storage for the
- // thread containing the location in the table where this thread will
- // write its counter data.
- //
- // name is just a debugging tag to label the thread, and it does not
- // need to be unique. It will be truncated to kMaxThreadNameLength-1
- // characters.
- //
- // On success, returns the slot id for this thread. On failure,
- // returns 0.
- int RegisterThread(const std::string& name);
-
- // Returns the number of threads currently registered. This is really not
- // useful except for diagnostics and debugging.
- int CountThreadsRegistered() const;
-
- // Find a counter in the StatsTable.
- //
- // Returns an id for the counter which can be used to call GetLocation().
- // If the counter does not exist, attempts to create a row for the new
- // counter. If there is no space in the table for the new counter,
- // returns 0.
- int FindCounter(const std::string& name);
-
- // TODO(mbelshe): implement RemoveCounter.
-
- // Gets the location of a particular value in the table based on
- // the counter id and slot id.
- int* GetLocation(int counter_id, int slot_id) const;
-
- // Gets the counter name at a particular row. If the row is empty,
- // returns NULL.
- const char* GetRowName(int index) const;
-
- // Gets the sum of the values for a particular row.
- int GetRowValue(int index) const;
-
- // Gets the sum of the values for a particular row for a given pid.
- int GetRowValue(int index, int pid) const;
-
- // Gets the sum of the values for a particular counter. If the counter
- // does not exist, creates the counter.
- int GetCounterValue(const std::string& name);
-
- // Gets the sum of the values for a particular counter for a given pid.
- // If the counter does not exist, creates the counter.
- int GetCounterValue(const std::string& name, int pid);
-
- // The maxinum number of counters/rows in the table.
- int GetMaxCounters() const;
-
- // The maxinum number of threads/columns in the table.
- int GetMaxThreads() const;
-
-#if defined(OS_POSIX)
- // Get the underlying shared memory handle for the table.
- base::SharedMemoryHandle GetSharedMemoryHandle() const;
-#endif
-
- // The maximum length (in characters) of a Thread's name including
- // null terminator, as stored in the shared memory.
- static const int kMaxThreadNameLength = 32;
-
- // The maximum length (in characters) of a Counter's name including
- // null terminator, as stored in the shared memory.
- static const int kMaxCounterNameLength = 64;
-
- // Convenience function to lookup a counter location for a
- // counter by name for the calling thread. Will register
- // the thread if it is not already registered.
- static int* FindLocation(const char *name);
-
- private:
- class Internal;
- struct TLSData;
- typedef hash_map<std::string, int> CountersMap;
-
- // Returns the space occupied by a thread in the table. Generally used
- // if a thread terminates but the process continues. This function
- // does not zero out the thread's counters.
- // Cannot be used inside a posix tls destructor.
- void UnregisterThread();
-
- // This variant expects the tls data to be passed in, so it is safe to
- // call from inside a posix tls destructor (see doc for pthread_key_create).
- void UnregisterThread(TLSData* tls_data);
-
- // The SlotReturnFunction is called at thread exit for each thread
- // which used the StatsTable.
- static void SlotReturnFunction(void* data);
-
- // Locates a free slot in the table. Returns a number > 0 on success,
- // or 0 on failure. The caller must hold the shared_memory lock when
- // calling this function.
- int FindEmptyThread() const;
-
- // Locates a counter in the table or finds an empty row. Returns a
- // number > 0 on success, or 0 on failure. The caller must hold the
- // shared_memory_lock when calling this function.
- int FindCounterOrEmptyRow(const std::string& name) const;
-
- // Internal function to add a counter to the StatsTable. Assumes that
- // the counter does not already exist in the table.
- //
- // name is a unique identifier for this counter, and will be truncated
- // to kMaxCounterNameLength-1 characters.
- //
- // On success, returns the counter_id for the newly added counter.
- // On failure, returns 0.
- int AddCounter(const std::string& name);
-
- // Get the TLS data for the calling thread. Returns NULL if none is
- // initialized.
- TLSData* GetTLSData() const;
-
- Internal* internal_;
-
- // The counters_lock_ protects the counters_ hash table.
- base::Lock counters_lock_;
-
- // The counters_ hash map is an in-memory hash of the counters.
- // It is used for quick lookup of counters, but is cannot be used
- // as a substitute for what is in the shared memory. Even though
- // we don't have a counter in our hash table, another process may
- // have created it.
- CountersMap counters_;
- ThreadLocalStorage::Slot tls_index_;
-
- DISALLOW_COPY_AND_ASSIGN(StatsTable);
-};
-
-} // namespace base
-
-#endif // BASE_METRICS_STATS_TABLE_H_
diff --git a/metrics/stats_table_unittest.cc b/metrics/stats_table_unittest.cc
deleted file mode 100644
index 38a21cc..0000000
--- a/metrics/stats_table_unittest.cc
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/shared_memory.h"
-#include "base/metrics/stats_counters.h"
-#include "base/metrics/stats_table.h"
-#include "base/process/kill.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/multiprocess_test.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-
-class StatsTableTest : public MultiProcessTest {
-};
-
-// Open a StatsTable and verify that we can write to each of the
-// locations in the table.
-TEST_F(StatsTableTest, VerifySlots) {
- const int kMaxThreads = 1;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-
- // Register a single thread.
- std::string thread_name = "mainThread";
- int slot_id = table.RegisterThread(thread_name);
- EXPECT_NE(slot_id, 0);
-
- // Fill up the table with counters.
- std::string counter_base_name = "counter";
- for (int index = 0; index < kMaxCounter; index++) {
- std::string counter_name = counter_base_name;
- base::StringAppendF(&counter_name, "counter.ctr%d", index);
- int counter_id = table.FindCounter(counter_name);
- EXPECT_GT(counter_id, 0);
- }
-
- // Try to allocate an additional thread. Verify it fails.
- slot_id = table.RegisterThread("too many threads");
- EXPECT_EQ(slot_id, 0);
-
- // Try to allocate an additional counter. Verify it fails.
- int counter_id = table.FindCounter(counter_base_name);
- EXPECT_EQ(counter_id, 0);
-}
-
-// CounterZero will continually be set to 0.
-const std::string kCounterZero = "CounterZero";
-// Counter1313 will continually be set to 1313.
-const std::string kCounter1313 = "Counter1313";
-// CounterIncrement will be incremented each time.
-const std::string kCounterIncrement = "CounterIncrement";
-// CounterDecrement will be decremented each time.
-const std::string kCounterDecrement = "CounterDecrement";
-// CounterMixed will be incremented by odd numbered threads and
-// decremented by even threads.
-const std::string kCounterMixed = "CounterMixed";
-// The number of thread loops that we will do.
-const int kThreadLoops = 100;
-
-class StatsTableThread : public SimpleThread {
- public:
- StatsTableThread(std::string name, int id)
- : SimpleThread(name),
- id_(id) {}
-
- void Run() override;
-
- private:
- int id_;
-};
-
-void StatsTableThread::Run() {
- // Each thread will open the shared memory and set counters
- // concurrently in a loop. We'll use some pauses to
- // mixup the thread scheduling.
-
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
- for (int index = 0; index < kThreadLoops; index++) {
- StatsCounter mixed_counter(kCounterMixed); // create this one in the loop
- zero_counter.Set(0);
- lucky13_counter.Set(1313);
- increment_counter.Increment();
- decrement_counter.Decrement();
- if (id_ % 2)
- mixed_counter.Decrement();
- else
- mixed_counter.Increment();
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
- }
-}
-
-// Create a few threads and have them poke on their counters.
-// See http://crbug.com/10611 for more information.
-// It is disabled on Win x64 incremental linking pending resolution of
-// http://crbug.com/251251.
-#if defined(OS_MACOSX) || defined(THREAD_SANITIZER) || \
- (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && \
- defined(INCREMENTAL_LINKING))
-#define MAYBE_MultipleThreads DISABLED_MultipleThreads
-#else
-#define MAYBE_MultipleThreads MultipleThreads
-#endif
-TEST_F(StatsTableTest, MAYBE_MultipleThreads) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- EXPECT_EQ(0, table.CountThreadsRegistered());
-
- // Spin up a set of threads to go bang on the various counters.
- // After we join the threads, we'll make sure the counters
- // contain the values we expected.
- StatsTableThread* threads[kMaxThreads];
-
- // Spawn the threads.
- for (int index = 0; index < kMaxThreads; index++) {
- threads[index] = new StatsTableThread("MultipleThreadsTest", index);
- threads[index]->Start();
- }
-
- // Wait for the threads to finish.
- for (int index = 0; index < kMaxThreads; index++) {
- threads[index]->Join();
- delete threads[index];
- }
-
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
- StatsCounter mixed_counter(kCounterMixed);
-
- // Verify the various counters are correct.
- std::string name;
- name = "c:" + kCounterZero;
- EXPECT_EQ(0, table.GetCounterValue(name));
- name = "c:" + kCounter1313;
- EXPECT_EQ(1313 * kMaxThreads,
- table.GetCounterValue(name));
- name = "c:" + kCounterIncrement;
- EXPECT_EQ(kMaxThreads * kThreadLoops,
- table.GetCounterValue(name));
- name = "c:" + kCounterDecrement;
- EXPECT_EQ(-kMaxThreads * kThreadLoops,
- table.GetCounterValue(name));
- name = "c:" + kCounterMixed;
- EXPECT_EQ((kMaxThreads % 2) * kThreadLoops,
- table.GetCounterValue(name));
- EXPECT_EQ(0, table.CountThreadsRegistered());
-}
-
-// This multiprocess test only runs on Windows. On Posix, the shared memory
-// handle is not sent between the processes properly.
-#if defined(OS_WIN)
-const std::string kMPTableName = "MultipleProcessStatTable";
-
-MULTIPROCESS_TEST_MAIN(StatsTableMultipleProcessMain) {
- // Each process will open the shared memory and set counters
- // concurrently in a loop. We'll use some pauses to
- // mixup the scheduling.
-
- StatsTable table(kMPTableName, 0, 0);
- StatsTable::set_current(&table);
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
- for (int index = 0; index < kThreadLoops; index++) {
- zero_counter.Set(0);
- lucky13_counter.Set(1313);
- increment_counter.Increment();
- decrement_counter.Decrement();
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
- }
- return 0;
-}
-
-// Create a few processes and have them poke on their counters.
-// This test is slow and flaky http://crbug.com/10611
-TEST_F(StatsTableTest, DISABLED_MultipleProcesses) {
- // Create a stats table.
- const int kMaxProcs = 20;
- const int kMaxCounter = 5;
- StatsTable table(kMPTableName, kMaxProcs, kMaxCounter);
- StatsTable::set_current(&table);
- EXPECT_EQ(0, table.CountThreadsRegistered());
-
- // Spin up a set of processes to go bang on the various counters.
- // After we join the processes, we'll make sure the counters
- // contain the values we expected.
- Process procs[kMaxProcs];
-
- // Spawn the processes.
- for (int16 index = 0; index < kMaxProcs; index++) {
- procs[index] = SpawnChild("StatsTableMultipleProcessMain");
- EXPECT_TRUE(procs[index].IsValid());
- }
-
- // Wait for the processes to finish.
- for (int index = 0; index < kMaxProcs; index++) {
- EXPECT_TRUE(WaitForSingleProcess(procs[index].Handle(),
- base::TimeDelta::FromMinutes(1)));
- procs[index].Close();
- }
-
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
-
- // Verify the various counters are correct.
- std::string name;
- name = "c:" + kCounterZero;
- EXPECT_EQ(0, table.GetCounterValue(name));
- name = "c:" + kCounter1313;
- EXPECT_EQ(1313 * kMaxProcs,
- table.GetCounterValue(name));
- name = "c:" + kCounterIncrement;
- EXPECT_EQ(kMaxProcs * kThreadLoops,
- table.GetCounterValue(name));
- name = "c:" + kCounterDecrement;
- EXPECT_EQ(-kMaxProcs * kThreadLoops,
- table.GetCounterValue(name));
- EXPECT_EQ(0, table.CountThreadsRegistered());
-}
-#endif
-
-class MockStatsCounter : public StatsCounter {
- public:
- explicit MockStatsCounter(const std::string& name)
- : StatsCounter(name) {}
- int* Pointer() { return GetPtr(); }
-};
-
-// Test some basic StatsCounter operations
-TEST_F(StatsTableTest, StatsCounter) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- MockStatsCounter foo("foo");
-
- // Test initial state.
- EXPECT_TRUE(foo.Enabled());
- ASSERT_NE(foo.Pointer(), static_cast<int*>(0));
- EXPECT_EQ(0, *(foo.Pointer()));
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-
- // Test Increment.
- while (*(foo.Pointer()) < 123) foo.Increment();
- EXPECT_EQ(123, table.GetCounterValue("c:foo"));
- foo.Add(0);
- EXPECT_EQ(123, table.GetCounterValue("c:foo"));
- foo.Add(-1);
- EXPECT_EQ(122, table.GetCounterValue("c:foo"));
-
- // Test Set.
- foo.Set(0);
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
- foo.Set(100);
- EXPECT_EQ(100, table.GetCounterValue("c:foo"));
- foo.Set(-1);
- EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
- foo.Set(0);
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-
- // Test Decrement.
- foo.Subtract(1);
- EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
- foo.Subtract(0);
- EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
- foo.Subtract(-1);
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-}
-
-class MockStatsCounterTimer : public StatsCounterTimer {
- public:
- explicit MockStatsCounterTimer(const std::string& name)
- : StatsCounterTimer(name) {}
-
- TimeTicks start_time() { return start_time_; }
- TimeTicks stop_time() { return stop_time_; }
-};
-
-// Test some basic StatsCounterTimer operations
-TEST_F(StatsTableTest, StatsCounterTimer) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- MockStatsCounterTimer bar("bar");
-
- // Test initial state.
- EXPECT_FALSE(bar.Running());
- EXPECT_TRUE(bar.start_time().is_null());
- EXPECT_TRUE(bar.stop_time().is_null());
-
- const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
- // Do some timing.
- bar.Start();
- PlatformThread::Sleep(kDuration);
- bar.Stop();
- EXPECT_GT(table.GetCounterValue("t:bar"), 0);
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
-
- // Verify that timing again is additive.
- bar.Start();
- PlatformThread::Sleep(kDuration);
- bar.Stop();
- EXPECT_GT(table.GetCounterValue("t:bar"), 0);
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
-}
-
-// Test some basic StatsRate operations
-TEST_F(StatsTableTest, StatsRate) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- StatsRate baz("baz");
-
- // Test initial state.
- EXPECT_FALSE(baz.Running());
- EXPECT_EQ(0, table.GetCounterValue("c:baz"));
- EXPECT_EQ(0, table.GetCounterValue("t:baz"));
-
- const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
- // Do some timing.
- baz.Start();
- PlatformThread::Sleep(kDuration);
- baz.Stop();
- EXPECT_EQ(1, table.GetCounterValue("c:baz"));
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:baz"));
-
- // Verify that timing again is additive.
- baz.Start();
- PlatformThread::Sleep(kDuration);
- baz.Stop();
- EXPECT_EQ(2, table.GetCounterValue("c:baz"));
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:baz"));
-}
-
-// Test some basic StatsScope operations
-TEST_F(StatsTableTest, StatsScope) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- StatsCounterTimer foo("foo");
- StatsRate bar("bar");
-
- // Test initial state.
- EXPECT_EQ(0, table.GetCounterValue("t:foo"));
- EXPECT_EQ(0, table.GetCounterValue("t:bar"));
- EXPECT_EQ(0, table.GetCounterValue("c:bar"));
-
- const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
- // Try a scope.
- {
- StatsScope<StatsCounterTimer> timer(foo);
- StatsScope<StatsRate> timer2(bar);
- PlatformThread::Sleep(kDuration);
- }
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:foo"));
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
- EXPECT_EQ(1, table.GetCounterValue("c:bar"));
-
- // Try a second scope.
- {
- StatsScope<StatsCounterTimer> timer(foo);
- StatsScope<StatsRate> timer2(bar);
- PlatformThread::Sleep(kDuration);
- }
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:foo"));
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
- EXPECT_EQ(2, table.GetCounterValue("c:bar"));
-}
-
-} // namespace base
diff --git a/observer_list_threadsafe.h b/observer_list_threadsafe.h
index b951a71..1a66333 100644
--- a/observer_list_threadsafe.h
+++ b/observer_list_threadsafe.h
@@ -168,7 +168,9 @@
// that at the completion of the Notify call that all Observers have
// been Notified. The notification may still be pending delivery.
template <class Method, class... Params>
- void Notify(Method m, const Params&... params) {
+ void Notify(const tracked_objects::Location& from_here,
+ Method m,
+ const Params&... params) {
UnboundMethod<ObserverType, Method, Tuple<Params...>> method(
m, MakeTuple(params...));
@@ -176,7 +178,7 @@
for (const auto& entry : observer_lists_) {
ObserverListContext* context = entry.second;
context->loop->PostTask(
- FROM_HERE,
+ from_here,
base::Bind(
&ObserverListThreadSafe<ObserverType>::template NotifyWrapper<
Method, Tuple<Params...>>,
diff --git a/observer_list_unittest.cc b/observer_list_unittest.cc
index 65ef934..636aa83 100644
--- a/observer_list_unittest.cc
+++ b/observer_list_unittest.cc
@@ -134,7 +134,7 @@
}
if (do_notifies_) {
- list_->Notify(&Foo::Observe, 10);
+ list_->Notify(FROM_HERE, &Foo::Observe, 10);
}
loop_->PostTask(
@@ -217,14 +217,14 @@
observer_list->AddObserver(&a);
observer_list->AddObserver(&b);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
observer_list->AddObserver(&evil);
observer_list->AddObserver(&c);
observer_list->AddObserver(&d);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(20, a.total);
@@ -247,7 +247,7 @@
observer_list->RemoveObserver(&a);
observer_list->RemoveObserver(&b);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(0, a.total);
@@ -258,7 +258,7 @@
// Should also do nothing.
observer_list->RemoveObserver(&b);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(10, a.total);
@@ -280,7 +280,7 @@
MessageLoop loop;
observer_list->AddObserver(&c);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(0, a.total);
@@ -294,7 +294,7 @@
observer_list->RemoveObserver(&c);
// Notify again.
- observer_list->Notify(&Foo::Observe, 20);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
RunLoop().RunUntilIdle();
EXPECT_EQ(20, a.total);
@@ -308,7 +308,7 @@
// Notifying should not fail but should also be a no-op.
MessageLoop loop;
observer_list->AddObserver(&b);
- observer_list->Notify(&Foo::Observe, 30);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
RunLoop().RunUntilIdle();
EXPECT_EQ(20, a.total);
@@ -353,7 +353,7 @@
a.AddFooToRemove(&a);
a.AddFooToRemove(&b);
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
RunLoop().RunUntilIdle();
}
@@ -392,7 +392,7 @@
if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
break;
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
}
@@ -424,7 +424,7 @@
observer_list->AddObserver(&a);
delete loop;
// Test passes if we don't crash here.
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
}
TEST(ObserverListTest, Existing) {
@@ -458,7 +458,7 @@
observer_list->AddObserver(&a);
observer_list->AddObserver(&b);
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
RunLoop().RunUntilIdle();
EXPECT_TRUE(b.added);
@@ -467,7 +467,7 @@
EXPECT_EQ(0, b.adder.total);
// Notify again to make sure b's adder is notified.
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
RunLoop().RunUntilIdle();
EXPECT_EQ(1, b.adder.total);
}
diff --git a/power_monitor/power_monitor.cc b/power_monitor/power_monitor.cc
index 14dc4b5..98c9c68 100644
--- a/power_monitor/power_monitor.cc
+++ b/power_monitor/power_monitor.cc
@@ -45,17 +45,18 @@
void PowerMonitor::NotifyPowerStateChange(bool battery_in_use) {
DVLOG(1) << "PowerStateChange: " << (battery_in_use ? "On" : "Off")
<< " battery";
- observers_->Notify(&PowerObserver::OnPowerStateChange, battery_in_use);
+ observers_->Notify(FROM_HERE, &PowerObserver::OnPowerStateChange,
+ battery_in_use);
}
void PowerMonitor::NotifySuspend() {
DVLOG(1) << "Power Suspending";
- observers_->Notify(&PowerObserver::OnSuspend);
+ observers_->Notify(FROM_HERE, &PowerObserver::OnSuspend);
}
void PowerMonitor::NotifyResume() {
DVLOG(1) << "Power Resuming";
- observers_->Notify(&PowerObserver::OnResume);
+ observers_->Notify(FROM_HERE, &PowerObserver::OnResume);
}
} // namespace base
diff --git a/process/kill_win.cc b/process/kill_win.cc
index 4d7225f..f280c6f 100644
--- a/process/kill_win.cc
+++ b/process/kill_win.cc
@@ -182,10 +182,9 @@
}
bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
- bool success = WaitForExitCodeWithTimeout(
- handle, exit_code, base::TimeDelta::FromMilliseconds(INFINITE));
- CloseProcessHandle(handle);
- return success;
+ // TODO(rvargas) crbug.com/417532: Remove this function.
+ Process process(handle);
+ return process.WaitForExit(exit_code);
}
bool WaitForExitCodeWithTimeout(ProcessHandle handle,
diff --git a/process/process_handle.h b/process/process_handle.h
index c99ea15..77f2c58 100644
--- a/process/process_handle.h
+++ b/process/process_handle.h
@@ -40,30 +40,12 @@
// Returns the ProcessHandle of the current process.
BASE_EXPORT ProcessHandle GetCurrentProcessHandle();
-
-
-// Closes the process handle opened by OpenProcessHandle.
-BASE_EXPORT void CloseProcessHandle(ProcessHandle process);
-
// Returns the unique ID for the specified process. This is functionally the
// same as Windows' GetProcessId(), but works on versions of Windows before
// Win XP SP1 as well.
+// DEPRECATED. New code should be using Process::Pid() instead.
BASE_EXPORT ProcessId GetProcId(ProcessHandle process);
-#if defined(OS_WIN)
-enum IntegrityLevel {
- INTEGRITY_UNKNOWN,
- LOW_INTEGRITY,
- MEDIUM_INTEGRITY,
- HIGH_INTEGRITY,
-};
-// Determine the integrity level of the specified process. Returns false
-// if the system does not support integrity levels (pre-Vista) or in the case
-// of an underlying system failure.
-BASE_EXPORT bool GetProcessIntegrityLevel(ProcessHandle process,
- IntegrityLevel* level);
-#endif
-
#if defined(OS_POSIX)
// Returns the path to the executable of the given process.
BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process);
diff --git a/process/process_handle_posix.cc b/process/process_handle_posix.cc
index a661ecd..4e332df 100644
--- a/process/process_handle_posix.cc
+++ b/process/process_handle_posix.cc
@@ -16,11 +16,6 @@
return GetCurrentProcId();
}
-void CloseProcessHandle(ProcessHandle process) {
- // See OpenProcessHandle, nothing to do.
- return;
-}
-
ProcessId GetProcId(ProcessHandle process) {
return process;
}
diff --git a/process/process_handle_win.cc b/process/process_handle_win.cc
index 30b2066..f2ffff8 100644
--- a/process/process_handle_win.cc
+++ b/process/process_handle_win.cc
@@ -20,64 +20,9 @@
return ::GetCurrentProcess();
}
-void CloseProcessHandle(ProcessHandle process) {
- CloseHandle(process);
-}
-
ProcessId GetProcId(ProcessHandle process) {
// This returns 0 if we have insufficient rights to query the process handle.
return GetProcessId(process);
}
-bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel *level) {
- if (!level)
- return false;
-
- if (win::GetVersion() < base::win::VERSION_VISTA)
- return false;
-
- HANDLE process_token;
- if (!OpenProcessToken(process, TOKEN_QUERY | TOKEN_QUERY_SOURCE,
- &process_token))
- return false;
-
- win::ScopedHandle scoped_process_token(process_token);
-
- DWORD token_info_length = 0;
- if (GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0,
- &token_info_length) ||
- GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- return false;
-
- scoped_ptr<char[]> token_label_bytes(new char[token_info_length]);
- if (!token_label_bytes.get())
- return false;
-
- TOKEN_MANDATORY_LABEL* token_label =
- reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
- if (!token_label)
- return false;
-
- if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
- token_info_length, &token_info_length))
- return false;
-
- DWORD integrity_level = *GetSidSubAuthority(token_label->Label.Sid,
- (DWORD)(UCHAR)(*GetSidSubAuthorityCount(token_label->Label.Sid)-1));
-
- if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID) {
- *level = LOW_INTEGRITY;
- } else if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
- integrity_level < SECURITY_MANDATORY_HIGH_RID) {
- *level = MEDIUM_INTEGRITY;
- } else if (integrity_level >= SECURITY_MANDATORY_HIGH_RID) {
- *level = HIGH_INTEGRITY;
- } else {
- NOTREACHED();
- return false;
- }
-
- return true;
-}
-
} // namespace base
diff --git a/process/process_info.h b/process/process_info.h
index e9e7b4e..85f204d 100644
--- a/process/process_info.h
+++ b/process/process_info.h
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef BASE_PROCESS_PROCESS_PROCESS_INFO_H_
-#define BASE_PROCESS_PROCESS_PROCESS_INFO_H_
+#ifndef BASE_PROCESS_PROCESS_INFO_H_
+#define BASE_PROCESS_PROCESS_INFO_H_
#include "base/base_export.h"
#include "base/basictypes.h"
+#include "build/build_config.h"
namespace base {
@@ -20,6 +21,24 @@
static const Time CreationTime();
};
+#if defined(OS_WIN)
+
+enum IntegrityLevel {
+ INTEGRITY_UNKNOWN,
+ LOW_INTEGRITY,
+ MEDIUM_INTEGRITY,
+ HIGH_INTEGRITY,
+};
+
+// Returns the integrity level of the process. Returns INTEGRITY_UNKNOWN if the
+// system does not support integrity levels (pre-Vista) or in the case of an
+// underlying system failure.
+BASE_EXPORT IntegrityLevel GetCurrentProcessIntegrityLevel();
+
+#endif // defined(OS_WIN)
+
+
+
} // namespace base
-#endif // BASE_PROCESS_PROCESS_PROCESS_INFO_H_
+#endif // BASE_PROCESS_PROCESS_INFO_H_
diff --git a/process/process_info_win.cc b/process/process_info_win.cc
index b930ae6..2b9c406 100644
--- a/process/process_info_win.cc
+++ b/process/process_info_win.cc
@@ -7,11 +7,14 @@
#include <windows.h>
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
namespace base {
-//static
+// static
const Time CurrentProcessInfo::CreationTime() {
FILETIME creation_time = {};
FILETIME ignore = {};
@@ -22,4 +25,55 @@
return Time::FromFileTime(creation_time);
}
+IntegrityLevel GetCurrentProcessIntegrityLevel() {
+ if (win::GetVersion() < base::win::VERSION_VISTA)
+ return INTEGRITY_UNKNOWN;
+
+ HANDLE process_token;
+ if (!::OpenProcessToken(::GetCurrentProcess(),
+ TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
+ return INTEGRITY_UNKNOWN;
+ }
+ win::ScopedHandle scoped_process_token(process_token);
+
+ DWORD token_info_length = 0;
+ if (::GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0,
+ &token_info_length) ||
+ ::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ return INTEGRITY_UNKNOWN;
+ }
+
+ scoped_ptr<char[]> token_label_bytes(new char[token_info_length]);
+ if (!token_label_bytes.get())
+ return INTEGRITY_UNKNOWN;
+
+ TOKEN_MANDATORY_LABEL* token_label =
+ reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
+ if (!token_label)
+ return INTEGRITY_UNKNOWN;
+
+ if (!::GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
+ token_info_length, &token_info_length)) {
+ return INTEGRITY_UNKNOWN;
+ }
+
+ DWORD integrity_level = *::GetSidSubAuthority(
+ token_label->Label.Sid,
+ static_cast<DWORD>(*::GetSidSubAuthorityCount(token_label->Label.Sid)-1));
+
+ if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID)
+ return LOW_INTEGRITY;
+
+ if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
+ integrity_level < SECURITY_MANDATORY_HIGH_RID) {
+ return MEDIUM_INTEGRITY;
+ }
+
+ if (integrity_level >= SECURITY_MANDATORY_HIGH_RID)
+ return HIGH_INTEGRITY;
+
+ NOTREACHED();
+ return INTEGRITY_UNKNOWN;
+}
+
} // namespace base
diff --git a/strings/string_util.cc b/strings/string_util.cc
index 8f334da..e084cb5 100644
--- a/strings/string_util.cc
+++ b/strings/string_util.cc
@@ -454,8 +454,8 @@
return DoLowerCaseEqualsASCII(a_begin, a_end, b);
}
-// TODO(jdduke): Remove guards after complete adoption of libc++ on Android.
-#if !defined(OS_ANDROID) || !defined(USE_STLPORT)
+// TODO(port): Resolve wchar_t/iterator issues that require OS_ANDROID here.
+#if !defined(OS_ANDROID)
bool LowerCaseEqualsASCII(const char* a_begin,
const char* a_end,
const char* b) {
@@ -467,7 +467,8 @@
const char* b) {
return DoLowerCaseEqualsASCII(a_begin, a_end, b);
}
-#endif // !defined(OS_ANDROID) || !defined(USE_STLPORT)
+
+#endif // !defined(OS_ANDROID)
bool EqualsASCII(const string16& a, const base::StringPiece& b) {
if (a.length() != b.length())
@@ -555,23 +556,103 @@
return base::ASCIIToUTF16(buf);
}
+// Runs in O(n) time in the length of |str|.
template<class StringType>
void DoReplaceSubstringsAfterOffset(StringType* str,
- size_t start_offset,
+ size_t offset,
const StringType& find_this,
const StringType& replace_with,
bool replace_all) {
- if ((start_offset == StringType::npos) || (start_offset >= str->length()))
+ DCHECK(!find_this.empty());
+
+ // If the find string doesn't appear, there's nothing to do.
+ offset = str->find(find_this, offset);
+ if (offset == StringType::npos)
return;
- DCHECK(!find_this.empty());
- for (size_t offs(str->find(find_this, start_offset));
- offs != StringType::npos; offs = str->find(find_this, offs)) {
- str->replace(offs, find_this.length(), replace_with);
- offs += replace_with.length();
+ // If we're only replacing one instance, there's no need to do anything
+ // complicated.
+ size_t find_length = find_this.length();
+ if (!replace_all) {
+ str->replace(offset, find_length, replace_with);
+ return;
+ }
- if (!replace_all)
- break;
+ // If the find and replace strings are the same length, we can simply use
+ // replace() on each instance, and finish the entire operation in O(n) time.
+ size_t replace_length = replace_with.length();
+ if (find_length == replace_length) {
+ do {
+ str->replace(offset, find_length, replace_with);
+ offset = str->find(find_this, offset + replace_length);
+ } while (offset != StringType::npos);
+ return;
+ }
+
+ // Since the find and replace strings aren't the same length, a loop like the
+ // one above would be O(n^2) in the worst case, as replace() will shift the
+ // entire remaining string each time. We need to be more clever to keep
+ // things O(n).
+ //
+ // If we're shortening the string, we can alternate replacements with shifting
+ // forward the intervening characters using memmove().
+ size_t str_length = str->length();
+ if (find_length > replace_length) {
+ size_t write_offset = offset;
+ do {
+ if (replace_length) {
+ str->replace(write_offset, replace_length, replace_with);
+ write_offset += replace_length;
+ }
+ size_t read_offset = offset + find_length;
+ offset = std::min(str->find(find_this, read_offset), str_length);
+ size_t length = offset - read_offset;
+ if (length) {
+ memmove(&(*str)[write_offset], &(*str)[read_offset],
+ length * sizeof(typename StringType::value_type));
+ write_offset += length;
+ }
+ } while (offset < str_length);
+ str->resize(write_offset);
+ return;
+ }
+
+ // We're lengthening the string. We can use alternating replacements and
+ // memmove() calls like above, but we need to precalculate the final string
+ // length and then expand from back-to-front to avoid overwriting the string
+ // as we're reading it, needing to shift, or having to copy to a second string
+ // temporarily.
+ size_t first_match = offset;
+
+ // First, calculate the final length and resize the string.
+ size_t final_length = str_length;
+ size_t expansion = replace_length - find_length;
+ size_t current_match;
+ do {
+ final_length += expansion;
+ // Minor optimization: save this offset into |current_match|, so that on
+ // exit from the loop, |current_match| will point at the last instance of
+ // the find string, and we won't need to find() it again immediately.
+ current_match = offset;
+ offset = str->find(find_this, offset + find_length);
+ } while (offset != StringType::npos);
+ str->resize(final_length);
+
+ // Now do the replacement loop, working backwards through the string.
+ for (size_t prev_match = str_length, write_offset = final_length; ;
+ current_match = str->rfind(find_this, current_match - 1)) {
+ size_t read_offset = current_match + find_length;
+ size_t length = prev_match - read_offset;
+ if (length) {
+ write_offset -= length;
+ memmove(&(*str)[write_offset], &(*str)[read_offset],
+ length * sizeof(typename StringType::value_type));
+ }
+ write_offset -= replace_length;
+ str->replace(write_offset, replace_length, replace_with);
+ if (current_match == first_match)
+ return;
+ prev_match = current_match;
}
}
diff --git a/system_monitor/system_monitor.cc b/system_monitor/system_monitor.cc
index 11dd000..99152ab 100644
--- a/system_monitor/system_monitor.cc
+++ b/system_monitor/system_monitor.cc
@@ -46,7 +46,7 @@
void SystemMonitor::NotifyDevicesChanged(DeviceType device_type) {
DVLOG(1) << "DevicesChanged with device type " << device_type;
devices_changed_observer_list_->Notify(
- &DevicesChangedObserver::OnDevicesChanged, device_type);
+ FROM_HERE, &DevicesChangedObserver::OnDevicesChanged, device_type);
}
} // namespace base
diff --git a/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java b/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
index 09e1fd6..797585f 100644
--- a/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
+++ b/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
@@ -16,20 +16,41 @@
/**
* Construct the full path of a test data file.
- * @param path Pathname relative to external/chrome/testing/data
+ * @param path Pathname relative to external/chrome/test/data
*/
public static String getTestFilePath(String path) {
+ // TODO(jbudorick): Remove DATA_DIR once everything has been isolated. crbug/400499
return PathUtils.getExternalStorageDirectory() + DATA_DIR + path;
}
+ // TODO(jbudorick): Remove this function once everything has been isolated and switched back
+ // to getTestFilePath. crbug/400499
+ /**
+ * Construct the full path of a test data file.
+ * @param path Pathname relative to external/
+ */
+ public static String getIsolatedTestFilePath(String path) {
+ return PathUtils.getExternalStorageDirectory() + "/" + path;
+ }
+
/**
* Construct a suitable URL for loading a test data file.
- * @param path Pathname relative to external/chrome/testing/data
+ * @param path Pathname relative to external/chrome/test/data
*/
public static String getTestFileUrl(String path) {
return "file://" + getTestFilePath(path);
}
+ // TODO(jbudorick): Remove this function once everything has been isolated and switched back
+ // to getTestFileUrl. crbug/400499
+ /**
+ * Construct a suitable URL for loading a test data file.
+ * @param path Pathname relative to external/
+ */
+ public static String getIsolatedTestFileUrl(String path) {
+ return "file://" + getIsolatedTestFilePath(path);
+ }
+
/**
* Construct a data:text/html URI for loading from an inline HTML.
* @param html An unencoded HTML
@@ -41,8 +62,7 @@
// ' '->'+' needs to be undone and replaced with ' '->'%20'
// to match the Data URI requirements.
String encoded =
- "data:text/html;utf-8," +
- java.net.URLEncoder.encode(html, "UTF-8");
+ "data:text/html;utf-8," + java.net.URLEncoder.encode(html, "UTF-8");
encoded = encoded.replace("+", "%20");
return encoded;
} catch (java.io.UnsupportedEncodingException e) {
diff --git a/test/multiprocess_test.h b/test/multiprocess_test.h
index e419503..b1c73df 100644
--- a/test/multiprocess_test.h
+++ b/test/multiprocess_test.h
@@ -33,16 +33,15 @@
// // Maybe set some options (e.g., |start_hidden| on Windows)....
//
// // Start a child process and run |a_test_func|.
-// base::ProcessHandle test_child_handle =
+// base::Process test_child_process =
// base::SpawnMultiProcessTestChild("a_test_func", command_line,
// options);
//
-// // Do stuff involving |test_child_handle| and the child process....
+// // Do stuff involving |test_child_process| and the child process....
//
// int rv = -1;
-// ASSERT_TRUE(base::WaitForExitCodeWithTimeout(
-// test_child_handle, &rv, TestTimeouts::action_timeout()));
-// base::CloseProcessHandle(test_child_handle);
+// ASSERT_TRUE(test_child_process.WaitForExitWithTimeout(
+// TestTimeouts::action_timeout(), &rv));
// EXPECT_EQ(0, rv);
// }
//
diff --git a/test/test_mock_time_task_runner.cc b/test/test_mock_time_task_runner.cc
index 442d991..a878280 100644
--- a/test/test_mock_time_task_runner.cc
+++ b/test/test_mock_time_task_runner.cc
@@ -6,18 +6,21 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
+#include "base/time/clock.h"
+#include "base/time/tick_clock.h"
namespace base {
namespace {
-// TickClock that always returns the then-current mock time of |task_runner| as
-// the current time.
+// MockTickClock --------------------------------------------------------------
+
+// TickClock that always returns the then-current mock time ticks of
+// |task_runner| as the current time ticks.
class MockTickClock : public TickClock {
public:
explicit MockTickClock(
scoped_refptr<const TestMockTimeTaskRunner> task_runner);
- ~MockTickClock() override;
// TickClock:
TimeTicks NowTicks() override;
@@ -33,22 +36,46 @@
: task_runner_(task_runner) {
}
-MockTickClock::~MockTickClock() {
+TimeTicks MockTickClock::NowTicks() {
+ return task_runner_->NowTicks();
}
-TimeTicks MockTickClock::NowTicks() {
- return task_runner_->GetCurrentMockTime();
+// MockClock ------------------------------------------------------------------
+
+// Clock that always returns the then-current mock time of |task_runner| as the
+// current time.
+class MockClock : public Clock {
+ public:
+ explicit MockClock(scoped_refptr<const TestMockTimeTaskRunner> task_runner);
+
+ // Clock:
+ Time Now() override;
+
+ private:
+ scoped_refptr<const TestMockTimeTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockClock);
+};
+
+MockClock::MockClock(scoped_refptr<const TestMockTimeTaskRunner> task_runner)
+ : task_runner_(task_runner) {
+}
+
+Time MockClock::Now() {
+ return task_runner_->Now();
}
} // namespace
+// TestMockTimeTaskRunner -----------------------------------------------------
+
bool TestMockTimeTaskRunner::TemporalOrder::operator()(
const TestPendingTask& first_task,
const TestPendingTask& second_task) const {
return first_task.GetTimeToRun() > second_task.GetTimeToRun();
}
-TestMockTimeTaskRunner::TestMockTimeTaskRunner() {
+TestMockTimeTaskRunner::TestMockTimeTaskRunner() : now_(Time::UnixEpoch()) {
}
TestMockTimeTaskRunner::~TestMockTimeTaskRunner() {
@@ -56,42 +83,38 @@
void TestMockTimeTaskRunner::FastForwardBy(TimeDelta delta) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_GE(delta, TimeDelta());
- OnBeforeSelectingTask();
-
- const base::TimeTicks original_now = now_;
- TestPendingTask task_info;
- while (DequeueNextTask(original_now, delta, &task_info)) {
- if (task_info.GetTimeToRun() - now_ > base::TimeDelta()) {
- now_ = task_info.GetTimeToRun();
- OnAfterTimePassed();
- }
-
- task_info.task.Run();
-
- OnAfterTaskRun();
- OnBeforeSelectingTask();
- }
-
- if (!delta.is_max() && now_ - original_now < delta) {
- now_ = original_now + delta;
- OnAfterTimePassed();
- }
+ const TimeTicks original_now_ticks = now_ticks_;
+ ProcessAllTasksNoLaterThan(delta);
+ ForwardClocksUntilTickTime(original_now_ticks + delta);
}
void TestMockTimeTaskRunner::RunUntilIdle() {
- FastForwardBy(TimeDelta());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ProcessAllTasksNoLaterThan(TimeDelta());
}
void TestMockTimeTaskRunner::FastForwardUntilNoTasksRemain() {
- FastForwardBy(TimeDelta::Max());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ProcessAllTasksNoLaterThan(TimeDelta::Max());
}
-TimeTicks TestMockTimeTaskRunner::GetCurrentMockTime() const {
+Time TestMockTimeTaskRunner::Now() const {
DCHECK(thread_checker_.CalledOnValidThread());
return now_;
}
+TimeTicks TestMockTimeTaskRunner::NowTicks() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return now_ticks_;
+}
+
+scoped_ptr<Clock> TestMockTimeTaskRunner::GetMockClock() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return make_scoped_ptr(new MockClock(this));
+}
+
scoped_ptr<TickClock> TestMockTimeTaskRunner::GetMockTickClock() const {
DCHECK(thread_checker_.CalledOnValidThread());
return make_scoped_ptr(new MockTickClock(this));
@@ -109,7 +132,8 @@
TimeDelta TestMockTimeTaskRunner::NextPendingTaskDelay() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return tasks_.empty() ? TimeDelta::Max() : tasks_.top().GetTimeToRun() - now_;
+ return tasks_.empty() ? TimeDelta::Max()
+ : tasks_.top().GetTimeToRun() - now_ticks_;
}
bool TestMockTimeTaskRunner::RunsTasksOnCurrentThread() const {
@@ -120,9 +144,9 @@
const tracked_objects::Location& from_here,
const Closure& task,
TimeDelta delay) {
- base::AutoLock scoped_lock(tasks_lock_);
- tasks_.push(
- TestPendingTask(from_here, task, now_, delay, TestPendingTask::NESTABLE));
+ AutoLock scoped_lock(tasks_lock_);
+ tasks_.push(TestPendingTask(from_here, task, now_ticks_, delay,
+ TestPendingTask::NESTABLE));
return true;
}
@@ -146,10 +170,36 @@
// Empty default implementation.
}
-bool TestMockTimeTaskRunner::DequeueNextTask(const base::TimeTicks& reference,
- const base::TimeDelta& max_delta,
+void TestMockTimeTaskRunner::ProcessAllTasksNoLaterThan(TimeDelta max_delta) {
+ DCHECK_GE(max_delta, TimeDelta());
+ const TimeTicks original_now_ticks = now_ticks_;
+ while (true) {
+ OnBeforeSelectingTask();
+ TestPendingTask task_info;
+ if (!DequeueNextTask(original_now_ticks, max_delta, &task_info))
+ break;
+ // If tasks were posted with a negative delay, task_info.GetTimeToRun() will
+ // be less than |now_ticks_|. ForwardClocksUntilTickTime() takes care of not
+ // moving the clock backwards in this case.
+ ForwardClocksUntilTickTime(task_info.GetTimeToRun());
+ task_info.task.Run();
+ OnAfterTaskRun();
+ }
+}
+
+void TestMockTimeTaskRunner::ForwardClocksUntilTickTime(TimeTicks later_ticks) {
+ if (later_ticks <= now_ticks_)
+ return;
+
+ now_ += later_ticks - now_ticks_;
+ now_ticks_ = later_ticks;
+ OnAfterTimePassed();
+}
+
+bool TestMockTimeTaskRunner::DequeueNextTask(const TimeTicks& reference,
+ const TimeDelta& max_delta,
TestPendingTask* next_task) {
- base::AutoLock scoped_lock(tasks_lock_);
+ AutoLock scoped_lock(tasks_lock_);
if (!tasks_.empty() &&
(tasks_.top().GetTimeToRun() - reference) <= max_delta) {
*next_task = tasks_.top();
diff --git a/test/test_mock_time_task_runner.h b/test/test_mock_time_task_runner.h
index 2f59892..1a651f6 100644
--- a/test/test_mock_time_task_runner.h
+++ b/test/test_mock_time_task_runner.h
@@ -14,11 +14,13 @@
#include "base/synchronization/lock.h"
#include "base/test/test_pending_task.h"
#include "base/threading/thread_checker.h"
-#include "base/time/tick_clock.h"
#include "base/time/time.h"
namespace base {
+class Clock;
+class TickClock;
+
// Runs pending tasks in the order of the tasks' post time + delay, and keeps
// track of a mock (virtual) tick clock time that can be fast-forwarded.
//
@@ -31,18 +33,26 @@
// turn call back into it (e.g., to post more tasks).
// - Tasks are stored in a priority queue, and executed in the increasing
// order of post time + delay.
+// - It does not check for overflow when doing time arithmetic. A sufficient
+// condition for preventing overflows is to make sure that the sum of all
+// posted task delays and fast-forward increments is still representable by
+// a TimeDelta, and that adding this delta to the starting values of Time
+// and TickTime is still within their respective range.
// - Non-nestable tasks are not supported.
// - Tasks aren't guaranteed to be destroyed immediately after they're run.
//
// This is a slightly more sophisticated version of TestSimpleTaskRunner, in
// that it supports running delayed tasks in the correct temporal order.
-class TestMockTimeTaskRunner : public base::SingleThreadTaskRunner {
+class TestMockTimeTaskRunner : public SingleThreadTaskRunner {
public:
+ // Constructs an instance whose virtual time will start at the Unix epoch, and
+ // whose time ticks will start at zero.
TestMockTimeTaskRunner();
// Fast-forwards virtual time by |delta|, causing all tasks with a remaining
- // delay less than or equal to |delta| to be executed.
- void FastForwardBy(base::TimeDelta delta);
+ // delay less than or equal to |delta| to be executed. |delta| must be
+ // non-negative.
+ void FastForwardBy(TimeDelta delta);
// Fast-forwards virtual time just until all tasks are executed.
void FastForwardUntilNoTasksRemain();
@@ -52,11 +62,18 @@
// elapse.
void RunUntilIdle();
- // Returns the current virtual time.
- TimeTicks GetCurrentMockTime() const;
+ // Returns the current virtual time (initially starting at the Unix epoch).
+ Time Now() const;
- // Returns a TickClock that uses the mock time of |this| as its time source.
- // The returned TickClock will hold a reference to |this|.
+ // Returns the current virtual tick time (initially starting at 0).
+ TimeTicks NowTicks() const;
+
+ // Returns a Clock that uses the virtual time of |this| as its time source.
+ // The returned Clock will hold a reference to |this|.
+ scoped_ptr<Clock> GetMockClock() const;
+
+ // Returns a TickClock that uses the virtual time ticks of |this| as its tick
+ // source. The returned TickClock will hold a reference to |this|.
scoped_ptr<TickClock> GetMockTickClock() const;
bool HasPendingTask() const;
@@ -66,12 +83,11 @@
// SingleThreadTaskRunner:
bool RunsTasksOnCurrentThread() const override;
bool PostDelayedTask(const tracked_objects::Location& from_here,
- const base::Closure& task,
- TimeDelta delay) override;
- bool PostNonNestableDelayedTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task,
- TimeDelta delay) override;
+ const Closure& task,
+ TimeDelta delay) override;
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay) override;
protected:
~TestMockTimeTaskRunner() override;
@@ -100,20 +116,32 @@
std::vector<TestPendingTask>,
TemporalOrder> TaskPriorityQueue;
+ // Core of the implementation for all flavors of fast-forward methods. Given a
+ // non-negative |max_delta|, runs all tasks with a remaining delay less than
+ // or equal to |max_delta|, and moves virtual time forward as needed for each
+ // processed task. Pass in TimeDelta::Max() as |max_delta| to run all tasks.
+ void ProcessAllTasksNoLaterThan(TimeDelta max_delta);
+
+ // Forwards |now_ticks_| until it equals |later_ticks|, and forwards |now_| by
+ // the same amount. Calls OnAfterTimePassed() if |later_ticks| > |now_ticks_|.
+ // Does nothing if |later_ticks| <= |now_ticks_|.
+ void ForwardClocksUntilTickTime(TimeTicks later_ticks);
+
// Returns the |next_task| to run if there is any with a running time that is
// at most |reference| + |max_delta|. This additional complexity is required
// so that |max_delta| == TimeDelta::Max() can be supported.
- bool DequeueNextTask(const base::TimeTicks& reference,
- const base::TimeDelta& max_delta,
+ bool DequeueNextTask(const TimeTicks& reference,
+ const TimeDelta& max_delta,
TestPendingTask* next_task);
- base::ThreadChecker thread_checker_;
- base::TimeTicks now_;
+ ThreadChecker thread_checker_;
+ Time now_;
+ TimeTicks now_ticks_;
// Temporally ordered heap of pending tasks. Must only be accessed while the
// |tasks_lock_| is held.
TaskPriorityQueue tasks_;
- base::Lock tasks_lock_;
+ Lock tasks_lock_;
DISALLOW_COPY_AND_ASSIGN(TestMockTimeTaskRunner);
};
diff --git a/test/test_pending_task.cc b/test/test_pending_task.cc
index 94989de..3f2c79d 100644
--- a/test/test_pending_task.cc
+++ b/test/test_pending_task.cc
@@ -34,7 +34,7 @@
TestPendingTask::~TestPendingTask() {}
-void TestPendingTask::AsValueInto(base::debug::TracedValue* state) const {
+void TestPendingTask::AsValueInto(base::trace_event::TracedValue* state) const {
state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
state->SetString("posting_function", location.ToString());
state->SetInteger("post_time", post_time.ToInternalValue());
@@ -50,10 +50,10 @@
state->SetInteger("delay", delay.ToInternalValue());
}
-scoped_refptr<base::debug::ConvertableToTraceFormat> TestPendingTask::AsValue()
- const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+TestPendingTask::AsValue() const {
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get());
return state;
}
diff --git a/test/test_pending_task.h b/test/test_pending_task.h
index 4a2b0e7..829baa6 100644
--- a/test/test_pending_task.h
+++ b/test/test_pending_task.h
@@ -57,8 +57,8 @@
// Functions for using test pending task with tracing, useful in unit
// testing.
- void AsValueInto(base::debug::TracedValue* state) const;
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::trace_event::TracedValue* state) const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
std::string ToString() const;
};
diff --git a/test/trace_event_analyzer.h b/test/trace_event_analyzer.h
index a8be893..57ff2b5 100644
--- a/test/trace_event_analyzer.h
+++ b/test/trace_event_analyzer.h
@@ -6,7 +6,7 @@
// specific trace events that were generated by the trace_event.h API.
//
// Basic procedure:
-// - Get trace events JSON string from base::debug::TraceLog.
+// - Get trace events JSON string from base::trace_event::TraceLog.
// - Create TraceAnalyzer with JSON string.
// - Call TraceAnalyzer::AssociateBeginEndEvents (optional).
// - Call TraceAnalyzer::AssociateEvents (zero or more times).
@@ -89,7 +89,8 @@
class QueryNode;
// trace_analyzer::TraceEvent is a more convenient form of the
-// base::debug::TraceEvent class to make tracing-based tests easier to write.
+// base::trace_event::TraceEvent class to make tracing-based tests easier to
+// write.
struct TraceEvent {
// ProcessThreadID contains a Process ID and Thread ID.
struct ProcessThreadID {
diff --git a/test/trace_event_analyzer_unittest.cc b/test/trace_event_analyzer_unittest.cc
index cc1f8a3..4bdb941 100644
--- a/test/trace_event_analyzer_unittest.cc
+++ b/test/trace_event_analyzer_unittest.cc
@@ -23,12 +23,12 @@
void BeginTracing();
void EndTracing();
- base::debug::TraceResultBuffer::SimpleOutput output_;
- base::debug::TraceResultBuffer buffer_;
+ base::trace_event::TraceResultBuffer::SimpleOutput output_;
+ base::trace_event::TraceResultBuffer buffer_;
};
void TraceEventAnalyzerTest::ManualSetUp() {
- ASSERT_TRUE(base::debug::TraceLog::GetInstance());
+ ASSERT_TRUE(base::trace_event::TraceLog::GetInstance());
buffer_.SetOutputCallback(output_.GetCallback());
output_.json_output.clear();
}
@@ -45,16 +45,16 @@
void TraceEventAnalyzerTest::BeginTracing() {
output_.json_output.clear();
buffer_.Start();
- base::debug::TraceLog::GetInstance()->SetEnabled(
- base::debug::CategoryFilter("*"),
- base::debug::TraceLog::RECORDING_MODE,
- base::debug::TraceOptions());
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ base::trace_event::CategoryFilter("*"),
+ base::trace_event::TraceLog::RECORDING_MODE,
+ base::trace_event::TraceOptions());
}
void TraceEventAnalyzerTest::EndTracing() {
- base::debug::TraceLog::GetInstance()->SetDisabled();
+ base::trace_event::TraceLog::GetInstance()->SetDisabled();
base::WaitableEvent flush_complete_event(false, false);
- base::debug::TraceLog::GetInstance()->Flush(
+ base::trace_event::TraceLog::GetInstance()->Flush(
base::Bind(&TraceEventAnalyzerTest::OnTraceDataCollected,
base::Unretained(this),
base::Unretained(&flush_complete_event)));
diff --git a/test/trace_to_file.cc b/test/trace_to_file.cc
index 948a6a7..4e2a332 100644
--- a/test/trace_to_file.cc
+++ b/test/trace_to_file.cc
@@ -51,10 +51,10 @@
path_ = path;
WriteFileHeader();
- debug::TraceLog::GetInstance()->SetEnabled(
- debug::CategoryFilter(categories),
- debug::TraceLog::RECORDING_MODE,
- debug::TraceOptions(debug::RECORD_UNTIL_FULL));
+ trace_event::TraceLog::GetInstance()->SetEnabled(
+ trace_event::CategoryFilter(categories),
+ trace_event::TraceLog::RECORDING_MODE,
+ trace_event::TraceOptions(trace_event::RECORD_UNTIL_FULL));
}
void TraceToFile::WriteFileHeader() {
@@ -74,7 +74,7 @@
static void OnTraceDataCollected(
Closure quit_closure,
- debug::TraceResultBuffer* buffer,
+ trace_event::TraceResultBuffer* buffer,
const scoped_refptr<RefCountedString>& json_events_str,
bool has_more_events) {
buffer->AddFragment(json_events_str->data());
@@ -87,14 +87,14 @@
return;
started_ = false;
- debug::TraceLog::GetInstance()->SetDisabled();
+ trace_event::TraceLog::GetInstance()->SetDisabled();
- debug::TraceResultBuffer buffer;
+ trace_event::TraceResultBuffer buffer;
buffer.SetOutputCallback(
Bind(&TraceToFile::TraceOutputCallback, Unretained(this)));
RunLoop run_loop;
- debug::TraceLog::GetInstance()->Flush(
+ trace_event::TraceLog::GetInstance()->Flush(
Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
run_loop.Run();
diff --git a/third_party/dynamic_annotations/BUILD.gn b/third_party/dynamic_annotations/BUILD.gn
index 9a47867..e52938c 100644
--- a/third_party/dynamic_annotations/BUILD.gn
+++ b/third_party/dynamic_annotations/BUILD.gn
@@ -4,9 +4,9 @@
source_set("dynamic_annotations") {
sources = [
+ "../valgrind/valgrind.h",
"dynamic_annotations.c",
"dynamic_annotations.h",
- "../valgrind/valgrind.h",
]
if (is_android && !is_debug) {
configs -= [ "//build/config/compiler:optimize" ]
diff --git a/third_party/dynamic_annotations/dynamic_annotations.gyp b/third_party/dynamic_annotations/dynamic_annotations.gyp
index 12cfb65..8d2e9ec 100644
--- a/third_party/dynamic_annotations/dynamic_annotations.gyp
+++ b/third_party/dynamic_annotations/dynamic_annotations.gyp
@@ -12,9 +12,9 @@
'../../../',
],
'sources': [
+ '../valgrind/valgrind.h',
'dynamic_annotations.c',
'dynamic_annotations.h',
- '../valgrind/valgrind.h',
],
'includes': [
'../../../build/android/increase_size_for_speed.gypi',
diff --git a/third_party/nspr/BUILD.gn b/third_party/nspr/BUILD.gn
index 516ca1f..c0b2ec2 100644
--- a/third_party/nspr/BUILD.gn
+++ b/third_party/nspr/BUILD.gn
@@ -3,7 +3,10 @@
# found in the LICENSE file.
source_set("nspr") {
- visibility = [ "//base" ]
+ visibility = [
+ "//base/*",
+ ]
+
sources = [
"prtime.cc",
"prtime.h",
diff --git a/time/time.cc b/time/time.cc
index ce9d12c..951f7ba 100644
--- a/time/time.cc
+++ b/time/time.cc
@@ -274,6 +274,22 @@
return leaky_unix_epoch_singleton_instance.Get().unix_epoch();
}
+TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
+ TimeDelta tick_interval) const {
+ // |interval_offset| is the offset from |this| to the next multiple of
+ // |tick_interval| after |tick_phase|, possibly negative if in the past.
+ TimeDelta interval_offset = TimeDelta::FromInternalValue(
+ (tick_phase - *this).ToInternalValue() % tick_interval.ToInternalValue());
+ // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
+ // Otherwise, if |tick_phase| was in the past, adjust forward to the next
+ // tick after |this|.
+ if (interval_offset.ToInternalValue() != 0 && tick_phase < *this) {
+ interval_offset += tick_interval;
+ }
+
+ return *this + interval_offset;
+}
+
std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
// This function formats a TimeTicks object as "bogo-microseconds".
// The origin and granularity of the count are platform-specific, and may very
diff --git a/time/time.h b/time/time.h
index eb86693..18de085 100644
--- a/time/time.h
+++ b/time/time.h
@@ -680,6 +680,12 @@
return ticks_;
}
+ // Returns |this| snapped to the next tick, given a |tick_phase| and
+ // repeating |tick_interval| in both directions. |this| may be before,
+ // after, or equal to the |tick_phase|.
+ TimeTicks SnappedToNextTick(TimeTicks tick_phase,
+ TimeDelta tick_interval) const;
+
TimeTicks& operator=(TimeTicks other) {
ticks_ = other.ticks_;
return *this;
diff --git a/time/time_unittest.cc b/time/time_unittest.cc
index 27f71b4..fdac59d 100644
--- a/time/time_unittest.cc
+++ b/time/time_unittest.cc
@@ -715,6 +715,62 @@
HighResClockTest(&TimeTicks::NowFromSystemTraceTime);
}
+TEST(TimeTicks, SnappedToNextTickBasic) {
+ base::TimeTicks phase = base::TimeTicks::FromInternalValue(4000);
+ base::TimeDelta interval = base::TimeDelta::FromInternalValue(1000);
+ base::TimeTicks timestamp;
+
+ // Timestamp in previous interval.
+ timestamp = base::TimeTicks::FromInternalValue(3500);
+ EXPECT_EQ(4000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp in next interval.
+ timestamp = base::TimeTicks::FromInternalValue(4500);
+ EXPECT_EQ(5000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp multiple intervals before.
+ timestamp = base::TimeTicks::FromInternalValue(2500);
+ EXPECT_EQ(3000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp multiple intervals after.
+ timestamp = base::TimeTicks::FromInternalValue(6500);
+ EXPECT_EQ(7000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp on previous interval.
+ timestamp = base::TimeTicks::FromInternalValue(3000);
+ EXPECT_EQ(3000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp on next interval.
+ timestamp = base::TimeTicks::FromInternalValue(5000);
+ EXPECT_EQ(5000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp equal to phase.
+ timestamp = base::TimeTicks::FromInternalValue(4000);
+ EXPECT_EQ(4000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+}
+
+TEST(TimeTicks, SnappedToNextTickOverflow) {
+ // int(big_timestamp / interval) < 0, so this causes a crash if the number of
+ // intervals elapsed is attempted to be stored in an int.
+ base::TimeTicks phase = base::TimeTicks::FromInternalValue(0);
+ base::TimeDelta interval = base::TimeDelta::FromInternalValue(4000);
+ base::TimeTicks big_timestamp =
+ base::TimeTicks::FromInternalValue(8635916564000);
+
+ EXPECT_EQ(8635916564000,
+ big_timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+ EXPECT_EQ(8635916564000,
+ big_timestamp.SnappedToNextTick(big_timestamp, interval)
+ .ToInternalValue());
+}
+
TEST(TimeDelta, FromAndIn) {
EXPECT_TRUE(TimeDelta::FromDays(2) == TimeDelta::FromHours(48));
EXPECT_TRUE(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180));
diff --git a/trace_event/memory_dump_manager.cc b/trace_event/memory_dump_manager.cc
new file mode 100644
index 0000000..bf631b3
--- /dev/null
+++ b/trace_event/memory_dump_manager.cc
@@ -0,0 +1,135 @@
+// Copyright 2015 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/trace_event/memory_dump_manager.h"
+
+#include <algorithm>
+
+#include "base/compiler_specific.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
+
+// TODO(primiano): in a separate CL rename DeleteTraceLogForTesting into
+// something like base::internal::TeardownSingletonForTesting so we don't have
+// to add a new friend to singleton each time.
+class DeleteTraceLogForTesting {
+ public:
+ static void Delete() {
+ Singleton<
+ base::trace_event::MemoryDumpManager,
+ LeakySingletonTraits<base::trace_event::MemoryDumpManager>>::OnExit(0);
+ }
+};
+
+namespace base {
+namespace trace_event {
+
+// TODO(primiano): this should be smarter and should do something similar to
+// trace event synthetic delays.
+const char MemoryDumpManager::kTraceCategory[] =
+ TRACE_DISABLED_BY_DEFAULT("memory-dumps");
+
+// static
+MemoryDumpManager* MemoryDumpManager::GetInstance() {
+ return Singleton<MemoryDumpManager,
+ LeakySingletonTraits<MemoryDumpManager>>::get();
+}
+
+// static
+void MemoryDumpManager::DeleteForTesting() {
+ DeleteTraceLogForTesting::Delete();
+}
+
+MemoryDumpManager::MemoryDumpManager() : memory_tracing_enabled_(0) {
+}
+
+MemoryDumpManager::~MemoryDumpManager() {
+ base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
+}
+
+void MemoryDumpManager::Initialize() {
+ TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list.
+ trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
+}
+
+void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
+ AutoLock lock(lock_);
+ if (std::find(dump_providers_registered_.begin(),
+ dump_providers_registered_.end(),
+ mdp) != dump_providers_registered_.end()) {
+ return;
+ }
+ dump_providers_registered_.push_back(mdp);
+}
+
+void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
+ AutoLock lock(lock_);
+
+ // Remove from the registered providers list.
+ auto it = std::find(dump_providers_registered_.begin(),
+ dump_providers_registered_.end(), mdp);
+ if (it != dump_providers_registered_.end())
+ dump_providers_registered_.erase(it);
+
+ // Remove from the enabled providers list. This is to deal with the case that
+ // UnregisterDumpProvider is called while the trace is enabled.
+ it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(),
+ mdp);
+ if (it != dump_providers_enabled_.end())
+ dump_providers_enabled_.erase(it);
+}
+
+void MemoryDumpManager::RequestDumpPoint(DumpPointType type) {
+ // TODO(primiano): this will have more logic, IPC broadcast & co.
+ // Bail out immediately if tracing is not enabled at all.
+ if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
+ return;
+
+ CreateLocalDumpPoint();
+}
+
+void MemoryDumpManager::BroadcastDumpRequest() {
+ NOTREACHED(); // TODO(primiano): implement IPC synchronization.
+}
+
+// Creates a dump point for the current process and appends it to the trace.
+void MemoryDumpManager::CreateLocalDumpPoint() {
+ AutoLock lock(lock_);
+ // TRACE_EVENT_* macros don't induce scoped_refptr type inference, hence we
+ // need the base ConvertableToTraceFormat and the upcast below. The
+ // alternative would be unnecessarily expensive (double Acquire/Release).
+ scoped_refptr<ConvertableToTraceFormat> pmd(new ProcessMemoryDump());
+
+ for (MemoryDumpProvider* dump_provider : dump_providers_enabled_) {
+ dump_provider->DumpInto(static_cast<ProcessMemoryDump*>(pmd.get()));
+ }
+
+ // TODO(primiano): add the dump point to the trace at this point.
+}
+
+void MemoryDumpManager::OnTraceLogEnabled() {
+ // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter
+ // to figure out (and cache) which dumpers should be enabled or not.
+ // For the moment piggy back everything on the generic "memory" category.
+ bool enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
+
+ AutoLock lock(lock_);
+ if (enabled) {
+ dump_providers_enabled_.assign(dump_providers_registered_.begin(),
+ dump_providers_registered_.end());
+ } else {
+ dump_providers_enabled_.clear();
+ }
+ subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
+}
+
+void MemoryDumpManager::OnTraceLogDisabled() {
+ AutoLock lock(lock_);
+ dump_providers_enabled_.clear();
+ subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/trace_event/memory_dump_manager.h b/trace_event/memory_dump_manager.h
new file mode 100644
index 0000000..fbc71d5
--- /dev/null
+++ b/trace_event/memory_dump_manager.h
@@ -0,0 +1,87 @@
+// Copyright 2015 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 BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
+
+#include <vector>
+
+#include "base/atomicops.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+#include "base/trace_event/trace_event.h"
+
+namespace base {
+namespace trace_event {
+
+class MemoryDumpProvider;
+
+// Captures the reason why a dump point is being requested. This is to allow
+// selective enabling of dump points, filtering and post-processing.
+enum class DumpPointType {
+ TASK_BEGIN, // Dumping memory at the beginning of a message-loop task.
+ TASK_END, // Dumping memory at the ending of a message-loop task.
+ PERIODIC_INTERVAL, // Dumping memory at periodic intervals.
+ EXPLICITLY_TRIGGERED, // Non maskable dump request.
+};
+
+// This is the interface exposed to the rest of the codebase to deal with
+// memory tracing. The main entry point for clients is represented by
+// RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
+class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
+ public:
+ static MemoryDumpManager* GetInstance();
+
+ // Invoked once per process to register the TraceLog observer.
+ void Initialize();
+
+ // MemoryDumpManager does NOT take memory ownership of |mdp|, which is
+ // expected to be a singleton.
+ void RegisterDumpProvider(MemoryDumpProvider* mdp);
+ void UnregisterDumpProvider(MemoryDumpProvider* mdp);
+
+ // Requests a memory dump. The dump might happen or not depending on the
+ // filters and categories specified when enabling tracing.
+ void RequestDumpPoint(DumpPointType type);
+
+ // TraceLog::EnabledStateObserver implementation.
+ void OnTraceLogEnabled() override;
+ void OnTraceLogDisabled() override;
+
+ private:
+ friend struct DefaultSingletonTraits<MemoryDumpManager>;
+ friend class MemoryDumpManagerTest;
+
+ static const char kTraceCategory[];
+
+ MemoryDumpManager();
+ virtual ~MemoryDumpManager();
+
+ // Tears down the singleton instance.
+ static void DeleteForTesting();
+
+ // Broadcasts the dump requests to the other processes.
+ void BroadcastDumpRequest();
+
+ // Creates a dump point for the current process and appends it to the trace.
+ void CreateLocalDumpPoint();
+
+ std::vector<MemoryDumpProvider*> dump_providers_registered_; // Not owned.
+ std::vector<MemoryDumpProvider*> dump_providers_enabled_; // Not owned.
+
+ // Protects from concurrent accesses to the |dump_providers_*|, e.g., tearing
+ // down logging while creating a dump point on another thread.
+ Lock lock_;
+
+ // Optimization to avoid attempting any dump point (i.e. to not walk an empty
+ // dump_providers_enabled_ list) when tracing is not enabled.
+ subtle::AtomicWord memory_tracing_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
diff --git a/trace_event/memory_dump_manager_unittest.cc b/trace_event/memory_dump_manager_unittest.cc
new file mode 100644
index 0000000..b5337e9
--- /dev/null
+++ b/trace_event/memory_dump_manager_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2015 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/trace_event/memory_dump_manager.h"
+
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace base {
+namespace trace_event {
+
+class MemoryDumpManagerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ MemoryDumpManager::GetInstance()->Initialize();
+ mdm_ = MemoryDumpManager::GetInstance();
+ }
+
+ void TearDown() override {
+ MemoryDumpManager::DeleteForTesting();
+ TraceLog::DeleteForTesting();
+ mdm_ = NULL;
+ }
+
+ protected:
+ const char* const kTraceCategory = MemoryDumpManager::kTraceCategory;
+
+ void EnableTracing(const char* category) {
+ TraceLog::GetInstance()->SetEnabled(
+ CategoryFilter(category), TraceLog::RECORDING_MODE, TraceOptions());
+ }
+
+ void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); }
+
+ MemoryDumpManager* mdm_;
+
+ private:
+ // We want our singleton torn down after each test.
+ ShadowingAtExitManager at_exit_manager_;
+};
+
+class MockDumpProvider : public MemoryDumpProvider {
+ public:
+ MOCK_METHOD1(DumpInto, void(ProcessMemoryDump* pmd));
+};
+
+TEST_F(MemoryDumpManagerTest, SingleDumper) {
+ MockDumpProvider mdp;
+ mdm_->RegisterDumpProvider(&mdp);
+
+ // Check that the dumper is not called if the memory category is not enabled.
+ EnableTracing("foo-and-bar-but-not-memory");
+ EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ // Now repeat enabling the memory category and check that the dumper is
+ // invoked this time.
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(3);
+ for (int i = 0; i < 3; ++i)
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ mdm_->UnregisterDumpProvider(&mdp);
+
+ // Finally check the unregister logic (no calls to the mdp after unregister).
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ TraceLog::GetInstance()->SetDisabled();
+}
+
+TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileTracing) {
+ MockDumpProvider mdp;
+ mdm_->RegisterDumpProvider(&mdp);
+
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(1);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+ mdm_->UnregisterDumpProvider(&mdp);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+ DisableTracing();
+}
+
+TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
+ MockDumpProvider mdp1;
+ MockDumpProvider mdp2;
+
+ // Enable only mdp1.
+ mdm_->RegisterDumpProvider(&mdp1);
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
+ EXPECT_CALL(mdp2, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ // Invert: enable mdp1 and disable mdp2.
+ mdm_->UnregisterDumpProvider(&mdp1);
+ mdm_->RegisterDumpProvider(&mdp2);
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
+ EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ // Enable both mdp1 and mdp2.
+ mdm_->RegisterDumpProvider(&mdp1);
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
+ EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+}
+
+} // namespace trace_Event
+} // namespace base
diff --git a/trace_event/memory_dump_provider.h b/trace_event/memory_dump_provider.h
new file mode 100644
index 0000000..18363c5
--- /dev/null
+++ b/trace_event/memory_dump_provider.h
@@ -0,0 +1,33 @@
+// Copyright 2015 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 BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+namespace base {
+namespace trace_event {
+
+class ProcessMemoryDump;
+
+// The contract interface that memory dump providers must implement.
+class BASE_EXPORT MemoryDumpProvider {
+ public:
+ // Called by the MemoryDumpManager when generating dump points.
+ virtual void DumpInto(ProcessMemoryDump* pmd) = 0;
+
+ protected:
+ MemoryDumpProvider() {}
+ virtual ~MemoryDumpProvider() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
diff --git a/trace_event/process_memory_dump.cc b/trace_event/process_memory_dump.cc
new file mode 100644
index 0000000..0a3e096
--- /dev/null
+++ b/trace_event/process_memory_dump.cc
@@ -0,0 +1,29 @@
+// Copyright 2015 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/trace_event/process_memory_dump.h"
+
+#include "base/json/json_writer.h"
+#include "base/values.h"
+
+namespace base {
+namespace trace_event {
+
+ProcessMemoryDump::ProcessMemoryDump() {
+}
+
+ProcessMemoryDump::~ProcessMemoryDump() {
+}
+
+void ProcessMemoryDump::AppendAsTraceFormat(std::string* out) const {
+ // Build up the [dumper name] -> [serialized snapshot] JSON dictionary.
+ DictionaryValue dict;
+ std::string json_dict;
+ // TODO(primiano): this will append here the actual dumps from the dumpers.
+ base::JSONWriter::Write(&dict, &json_dict);
+ *out += json_dict;
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/trace_event/process_memory_dump.h b/trace_event/process_memory_dump.h
new file mode 100644
index 0000000..ae42987
--- /dev/null
+++ b/trace_event/process_memory_dump.h
@@ -0,0 +1,37 @@
+// Copyright 2015 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 BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
+#define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/trace_event/trace_event_impl.h"
+
+namespace base {
+namespace trace_event {
+
+// A container which holds the dumps produced by the MemoryDumpProvider(s)
+// for a specific process. ProcessMemoryDump is as a strongly typed container
+// which enforces the data model for each memory dump point.
+// At trace generation time (i.e. when AppendAsTraceFormat is called) the
+// ProcessMemoryDump will compose a key-value dictionary of the various dumps
+// obtained during at trace dump point time.
+class BASE_EXPORT ProcessMemoryDump : public ConvertableToTraceFormat {
+ public:
+ ProcessMemoryDump();
+
+ // ConvertableToTraceFormat implementation.
+ void AppendAsTraceFormat(std::string* out) const override;
+
+ private:
+ ~ProcessMemoryDump() override;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
diff --git a/trace_event/trace_event.h b/trace_event/trace_event.h
index c8583d7..07a2afa 100644
--- a/trace_event/trace_event.h
+++ b/trace_event/trace_event.h
@@ -1603,12 +1603,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::TraceScopedTrackableObject;
-} // namespace debug
-} // namespace base
-
#endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */
diff --git a/trace_event/trace_event_argument.h b/trace_event/trace_event_argument.h
index 43a0f38..78d37d4 100644
--- a/trace_event/trace_event_argument.h
+++ b/trace_event/trace_event_argument.h
@@ -56,12 +56,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::TracedValue;
-} // namespace debug
-} // namespace base
-
#endif // BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
diff --git a/trace_event/trace_event_impl.cc b/trace_event/trace_event_impl.cc
index 95cf06d..9ca0ddc 100644
--- a/trace_event/trace_event_impl.cc
+++ b/trace_event/trace_event_impl.cc
@@ -1908,11 +1908,13 @@
AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
DCHECK(name);
+ DCHECK(!timestamp.is_null());
if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
id ^= process_id_hash_;
- TimeTicks now = OffsetTimestamp(timestamp);
+ TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp);
+ TimeTicks now = OffsetNow();
TimeTicks thread_now = ThreadNow();
ThreadLocalEventBuffer* thread_local_event_buffer = NULL;
@@ -1985,8 +1987,8 @@
}
if (trace_event) {
- trace_event->Initialize(thread_id, now, thread_now, phase,
- category_group_enabled, name, id,
+ trace_event->Initialize(thread_id, offset_event_timestamp, thread_now,
+ phase, category_group_enabled, name, id,
num_args, arg_names, arg_types, arg_values,
convertable_values, flags);
@@ -2024,7 +2026,7 @@
EventCallback event_callback = reinterpret_cast<EventCallback>(
subtle::NoBarrier_Load(&event_callback_));
if (event_callback) {
- event_callback(now,
+ event_callback(offset_event_timestamp,
phase == TRACE_EVENT_PHASE_COMPLETE ?
TRACE_EVENT_PHASE_BEGIN : phase,
category_group_enabled, name, id,
@@ -2033,6 +2035,9 @@
}
}
+ // Use |now| instead of |offset_event_timestamp| to compute overhead, because
+ // event timestamp may be not the real time that we started to add the event
+ // (e.g. event with zero timestamp or that was generated some time ago).
if (thread_local_event_buffer)
thread_local_event_buffer->ReportOverhead(now, thread_now);
diff --git a/trace_event/trace_event_impl.h b/trace_event/trace_event_impl.h
index 742f6b6..efa20c4 100644
--- a/trace_event/trace_event_impl.h
+++ b/trace_event/trace_event_impl.h
@@ -810,21 +810,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::CategoryFilter;
-using base::trace_event::ConvertableToTraceFormat;
-using base::trace_event::RECORD_UNTIL_FULL;
-using base::trace_event::RECORD_CONTINUOUSLY;
-using base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE;
-using base::trace_event::TraceEventHandle;
-using base::trace_event::TraceLog;
-using base::trace_event::TraceLogStatus;
-using base::trace_event::TraceOptions;
-using base::trace_event::TraceResultBuffer;
-} // namespace debug
-} // namespace base
-
#endif // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
diff --git a/trace_event/trace_event_win.h b/trace_event/trace_event_win.h
index dcb5aac..4161361 100644
--- a/trace_event/trace_event_win.h
+++ b/trace_event/trace_event_win.h
@@ -122,18 +122,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::kChromeTraceProviderName;
-using base::trace_event::kTraceEventClass32;
-using base::trace_event::kTraceEventClass64;
-using base::trace_event::kTraceEventTypeBegin;
-using base::trace_event::kTraceEventTypeEnd;
-using base::trace_event::kTraceEventTypeInstant;
-using base::trace_event::TraceEventETWProvider;
-} // namespace debug
-} // namespace base
-
#endif // BASE_TRACE_EVENT_TRACE_EVENT_WIN_H_