summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2011-05-11 20:53:37 +0100
committerKristian Monsen <kristianm@google.com>2011-05-16 13:54:48 +0100
commit21d179b334e59e9a3bfcaed4c4430bef1bc5759d (patch)
tree64e2bb6da27af6a5c93ca34f6051584aafbfcb9e /base
parent0c63f00edd6ed0482fd5cbcea937ca088baf7858 (diff)
downloadexternal_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.zip
external_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.tar.gz
external_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.tar.bz2
Merge Chromium at 10.0.621.0: Initial merge by git.
Change-Id: I070cc91c608dfa4a968a5a54c173260765ac8097
Diffstat (limited to 'base')
-rw-r--r--base/atomicops.h6
-rw-r--r--base/base.gyp18
-rw-r--r--base/base.gypi412
-rw-r--r--base/base_paths_linux.cc10
-rw-r--r--base/callback.h5
-rw-r--r--base/chrome_application_mac.h61
-rw-r--r--base/chrome_application_mac.mm68
-rw-r--r--base/command_line.cc18
-rw-r--r--base/command_line.h7
-rw-r--r--base/crypto/cssm_init.cc22
-rw-r--r--base/crypto/rsa_private_key.h2
-rw-r--r--base/crypto/rsa_private_key_openssl.cc13
-rw-r--r--base/crypto/signature_creator_openssl.cc3
-rw-r--r--base/crypto/signature_verifier_openssl.cc3
-rw-r--r--base/data/data_pack_unittest/sample.pakbin80 -> 0 bytes
-rw-r--r--base/data_pack.cc216
-rw-r--r--base/data_pack.h62
-rw-r--r--base/data_pack_unittest.cc73
-rw-r--r--base/debug/debugger_posix.cc18
-rw-r--r--base/debug/debugger_win.cc3
-rw-r--r--base/debug/leak_tracker.h10
-rw-r--r--base/debug/stack_trace_posix.cc4
-rw-r--r--base/debug/stack_trace_win.cc4
-rw-r--r--base/debug/trace_event.cc14
-rw-r--r--base/debug/trace_event.h8
-rw-r--r--base/debug/trace_event_win.cc6
-rw-r--r--base/debug/trace_event_win.h2
-rw-r--r--base/debug/trace_event_win_unittest.cc4
-rw-r--r--base/file_descriptor_shuffle.h6
-rw-r--r--base/file_util.cc8
-rw-r--r--base/file_util_deprecated.h2
-rw-r--r--base/file_util_posix.cc5
-rw-r--r--base/file_util_win.cc8
-rw-r--r--base/file_version_info.h51
-rw-r--r--base/file_version_info_mac.h49
-rw-r--r--base/file_version_info_mac.mm110
-rw-r--r--base/file_version_info_win.cc37
-rw-r--r--base/file_version_info_win.h34
-rw-r--r--base/global_descriptors_posix.cc8
-rw-r--r--base/global_descriptors_posix.h3
-rw-r--r--base/hash_tables.h4
-rw-r--r--base/i18n/break_iterator.cc101
-rw-r--r--base/i18n/break_iterator.h108
-rw-r--r--base/i18n/break_iterator_unittest.cc308
-rw-r--r--base/i18n/file_util_icu.cc46
-rw-r--r--base/i18n/number_formatting.cc26
-rw-r--r--base/i18n/rtl.cc52
-rw-r--r--base/i18n/rtl.h1
-rw-r--r--base/i18n/time_formatting.cc23
-rw-r--r--base/i18n/time_formatting.h14
-rw-r--r--base/i18n/word_iterator.cc70
-rw-r--r--base/i18n/word_iterator.h89
-rw-r--r--base/i18n/word_iterator_unittest.cc117
-rw-r--r--base/image_util.cc72
-rw-r--r--base/image_util.h67
-rw-r--r--base/lazy_instance.h15
-rw-r--r--base/linux_util.cc4
-rw-r--r--base/logging.cc38
-rw-r--r--base/logging_win.cc19
-rw-r--r--base/logging_win.h8
-rw-r--r--base/mac/cocoa_protocols.h (renamed from base/cocoa_protocols_mac.h)0
-rw-r--r--base/mac_util.h62
-rw-r--r--base/mac_util.mm21
-rw-r--r--base/mac_util_unittest.mm4
-rw-r--r--base/message_loop.cc25
-rw-r--r--base/message_loop_proxy_impl.h6
-rw-r--r--base/message_loop_unittest.cc4
-rw-r--r--base/message_pump_glib.cc4
-rw-r--r--base/message_pump_glib.h2
-rw-r--r--base/message_pump_glib_x.cc35
-rw-r--r--base/message_pump_glib_x.h4
-rw-r--r--base/message_pump_glib_x_dispatch.h15
-rw-r--r--base/message_pump_mac.h17
-rw-r--r--base/message_pump_mac.mm11
-rw-r--r--base/metrics/field_trial.cc24
-rw-r--r--base/metrics/field_trial.h10
-rw-r--r--base/metrics/histogram.cc63
-rw-r--r--base/metrics/histogram.h8
-rw-r--r--base/mime_util_xdg.cc27
-rw-r--r--base/nsimage_cache_mac.h33
-rw-r--r--base/nsimage_cache_mac.mm73
-rw-r--r--base/nss_util.cc4
-rw-r--r--base/nss_util.h4
-rw-r--r--base/openssl_util.cc30
-rw-r--r--base/openssl_util.h4
-rw-r--r--base/path_service.cc18
-rw-r--r--base/path_service.h5
-rw-r--r--base/pickle.cc3
-rw-r--r--base/pickle.h1
-rw-r--r--base/pickle_unittest.cc11
-rw-r--r--base/platform_thread_mac.mm20
-rw-r--r--base/platform_thread_posix.cc4
-rw-r--r--base/platform_thread_win.cc8
-rw-r--r--base/process_util.cc12
-rw-r--r--base/process_util.h45
-rw-r--r--base/process_util_linux.cc33
-rw-r--r--base/process_util_mac.mm130
-rw-r--r--base/process_util_posix.cc52
-rw-r--r--base/process_util_unittest.cc172
-rw-r--r--base/process_util_win.cc86
-rw-r--r--base/raw_scoped_refptr_mismatch_checker.h225
-rw-r--r--base/scoped_handle_win.h3
-rw-r--r--base/scoped_variant_win.h9
-rw-r--r--base/singleton.h67
-rw-r--r--base/singleton_unittest.cc186
-rw-r--r--base/string_util.cc47
-rw-r--r--base/string_util.h8
-rw-r--r--base/string_util_unittest.cc27
-rw-r--r--base/stringprintf.h1
-rw-r--r--base/task.h23
-rw-r--r--base/task_unittest.cc52
-rw-r--r--base/template_util.h47
-rw-r--r--base/test/mock_chrome_application_mac.h28
-rw-r--r--base/test/mock_chrome_application_mac.mm19
-rw-r--r--base/test/test_switches.cc1
-rw-r--r--base/test/test_switches.h1
-rw-r--r--base/test/test_timeouts.cc6
-rw-r--r--base/test/test_timeouts.h4
-rw-r--r--base/third_party/nspr/prcpucfg.h4
-rw-r--r--base/time_win.cc32
-rw-r--r--base/tuple.h6
-rw-r--r--base/unix_domain_socket_posix.cc143
-rw-r--r--base/unix_domain_socket_posix.h43
-rw-r--r--base/values.cc125
-rw-r--r--base/values.h47
-rw-r--r--base/values_unittest.cc156
-rw-r--r--base/values_util.cc4
-rw-r--r--base/values_util.h4
-rw-r--r--base/version.cc17
-rw-r--r--base/version.h7
-rw-r--r--base/waitable_event_watcher.h2
-rw-r--r--base/watchdog_unittest.cc2
-rw-r--r--base/win/registry.cc10
-rw-r--r--base/win/registry.h13
-rw-r--r--base/win/scoped_variant.cc2
-rw-r--r--base/worker_pool_mac.h33
-rw-r--r--base/worker_pool_mac.mm205
-rw-r--r--base/worker_pool_posix.cc (renamed from base/worker_pool_linux.cc)38
-rw-r--r--base/worker_pool_posix.h (renamed from base/worker_pool_linux.h)52
-rw-r--r--base/worker_pool_posix_unittest.cc (renamed from base/worker_pool_linux_unittest.cc)30
140 files changed, 2393 insertions, 3001 deletions
diff --git a/base/atomicops.h b/base/atomicops.h
index cf2f2bb..445696b 100644
--- a/base/atomicops.h
+++ b/base/atomicops.h
@@ -43,8 +43,14 @@ typedef __w64 int32 Atomic32;
#ifdef ARCH_CPU_64_BITS
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
// means Atomic64 and AtomicWord should be the same type on 64-bit.
+#if defined(OS_NACL)
+// NaCl's intptr_t is not actually 64-bits on 64-bit!
+// http://code.google.com/p/nativeclient/issues/detail?id=1162
+typedef int64_t Atomic64;
+#else
typedef intptr_t Atomic64;
#endif
+#endif
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
// Atomic64 routines below, depending on your architecture.
diff --git a/base/base.gyp b/base/base.gyp
index f68359a..075561b 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -31,6 +31,8 @@
'base',
],
'sources': [
+ 'i18n/break_iterator.cc',
+ 'i18n/break_iterator.h',
'i18n/char_iterator.cc',
'i18n/char_iterator.h',
'i18n/file_util_icu.cc',
@@ -47,8 +49,6 @@
'i18n/rtl.h',
'i18n/time_formatting.cc',
'i18n/time_formatting.h',
- 'i18n/word_iterator.cc',
- 'i18n/word_iterator.h',
],
},
{
@@ -74,7 +74,6 @@
'crypto/signature_creator_unittest.cc',
'crypto/signature_verifier_unittest.cc',
'crypto/symmetric_key_unittest.cc',
- 'data_pack_unittest.cc',
'debug/leak_tracker_unittest.cc',
'debug/stack_trace_unittest.cc',
'debug/trace_event_win_unittest.cc',
@@ -87,11 +86,11 @@
'gmock_unittest.cc',
'hmac_unittest.cc',
'id_map_unittest.cc',
+ 'i18n/break_iterator_unittest.cc',
'i18n/char_iterator_unittest.cc',
'i18n/file_util_icu_unittest.cc',
'i18n/icu_string_conversions_unittest.cc',
'i18n/rtl_unittest.cc',
- 'i18n/word_iterator_unittest.cc',
'json/json_reader_unittest.cc',
'json/json_writer_unittest.cc',
'json/string_escape_unittest.cc',
@@ -141,6 +140,7 @@
'sys_string_conversions_mac_unittest.mm',
'sys_string_conversions_unittest.cc',
'task_queue_unittest.cc',
+ 'task_unittest.cc',
'thread_checker_unittest.cc',
'thread_collision_warner_unittest.cc',
'thread_local_storage_unittest.cc',
@@ -171,13 +171,9 @@
'win/scoped_bstr_unittest.cc',
'win/scoped_comptr_unittest.cc',
'win/scoped_variant_unittest.cc',
+ 'worker_pool_posix_unittest.cc',
'worker_pool_unittest.cc',
],
- 'include_dirs': [
- # word_iterator.h (used by word_iterator_unittest.cc) leaks an ICU
- # #include for unicode/uchar.h. This should probably be cleaned up.
- '../third_party/icu/public/common',
- ],
'dependencies': [
'base',
'base_i18n',
@@ -189,7 +185,6 @@
['OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', {
'sources!': [
'file_version_info_unittest.cc',
- 'worker_pool_linux_unittest.cc',
],
'sources': [
'nix/xdg_util_unittest.cc',
@@ -222,6 +217,7 @@
'sources!': [
'dir_reader_posix_unittest.cc',
'file_descriptor_shuffle_unittest.cc',
+ 'worker_pool_posix_unittest.cc',
],
}, { # OS != "win"
'sources/': [
@@ -261,6 +257,8 @@
],
'sources': [
'perftimer.cc',
+ 'test/mock_chrome_application_mac.h',
+ 'test/mock_chrome_application_mac.mm',
'test/multiprocess_test.cc',
'test/multiprocess_test.h',
'test/perf_test_suite.cc',
diff --git a/base/base.gypi b/base/base.gypi
index a71ccf4..3eaedfa 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -6,7 +6,6 @@
'target_defaults': {
'variables': {
'base_target': 0,
- 'base_extra_target': 0,
},
'target_conditions': [
# This part is shared between the targets defined below.
@@ -42,9 +41,6 @@
'callback.h',
'cancellation_flag.cc',
'cancellation_flag.h',
- 'chrome_application_mac.h',
- 'chrome_application_mac.mm',
- 'cocoa_protocols_mac.h',
'command_line.cc',
'command_line.h',
'compiler_specific.h',
@@ -120,6 +116,7 @@
'logging_win.cc',
'mac_util.h',
'mac_util.mm',
+ 'mac/cocoa_protocols.h',
'mac/scoped_aedesc.h',
'mac/scoped_cftyperef.h',
'mac/scoped_nsautorelease_pool.h',
@@ -272,7 +269,6 @@
'tracked_objects.cc',
'tracked_objects.h',
'tuple.h',
- 'unix_domain_socket_posix.cc',
'utf_offset_string_conversions.cc',
'utf_offset_string_conversions.h',
'utf_string_conversion_utils.cc',
@@ -323,10 +319,8 @@
'win_util.cc',
'win_util.h',
'worker_pool.h',
- 'worker_pool_linux.cc',
- 'worker_pool_linux.h',
- 'worker_pool_mac.h',
- 'worker_pool_mac.mm',
+ 'worker_pool_posix.cc',
+ 'worker_pool_posix.h',
'worker_pool_win.cc',
'nix/xdg_util.h',
'nix/xdg_util.cc',
@@ -363,13 +357,6 @@
],
},
],
- # Temporarily include linux implementation while debugging a
- # workerpool issue. See http://crbug.com/20471 and
- # http://crbug.com/60426
- [ 'OS == "mac"', {
- 'sources/': [ ['include', '(^|/)worker_pool_linux\.cc$'] ],
- },
- ],
[ 'OS != "mac"', {
'sources!': [
'scoped_aedesc.h'
@@ -406,180 +393,6 @@
},],
],
}],
- ['base_extra_target==1', {
- 'sources': [
- 'crypto/capi_util.cc',
- 'crypto/capi_util.h',
- 'crypto/cssm_init.cc',
- 'crypto/cssm_init.h',
- 'crypto/encryptor.h',
- 'crypto/encryptor_mac.cc',
- 'crypto/encryptor_nss.cc',
- 'crypto/encryptor_openssl.cc',
- 'crypto/encryptor_win.cc',
- 'crypto/rsa_private_key.h',
- 'crypto/rsa_private_key.cc',
- 'crypto/rsa_private_key_mac.cc',
- 'crypto/rsa_private_key_nss.cc',
- 'crypto/rsa_private_key_openssl.cc',
- 'crypto/rsa_private_key_win.cc',
- 'crypto/signature_creator.h',
- 'crypto/signature_creator_mac.cc',
- 'crypto/signature_creator_nss.cc',
- 'crypto/signature_creator_openssl.cc',
- 'crypto/signature_creator_win.cc',
- 'crypto/signature_verifier.h',
- 'crypto/signature_verifier_mac.cc',
- 'crypto/signature_verifier_nss.cc',
- 'crypto/signature_verifier_openssl.cc',
- 'crypto/signature_verifier_win.cc',
- 'crypto/symmetric_key.h',
- 'crypto/symmetric_key_mac.cc',
- 'crypto/symmetric_key_nss.cc',
- 'crypto/symmetric_key_openssl.cc',
- 'crypto/symmetric_key_win.cc',
- 'third_party/nspr/prcpucfg.h',
- 'third_party/nspr/prcpucfg_win.h',
- 'third_party/nspr/prtypes.h',
- 'third_party/nss/blapi.h',
- 'third_party/nss/blapit.h',
- 'third_party/nss/sha256.h',
- 'third_party/nss/sha512.cc',
- 'third_party/purify/pure.h',
- 'third_party/purify/pure_api.c',
- 'third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
- 'third_party/xdg_user_dirs/xdg_user_dir_lookup.h',
- 'auto_reset.h',
- 'base64.cc',
- 'base64.h',
- 'data_pack.cc',
- 'event_recorder.cc',
- 'event_recorder.h',
- 'event_recorder_stubs.cc',
- 'file_descriptor_shuffle.cc',
- 'file_descriptor_shuffle.h',
- 'hmac.h',
- 'hmac_mac.cc',
- 'hmac_nss.cc',
- 'hmac_openssl.cc',
- 'hmac_win.cc',
- 'image_util.cc',
- 'image_util.h',
- 'linux_util.cc',
- 'linux_util.h',
- 'md5.cc',
- 'md5.h',
- 'message_pump_glib.cc',
- 'message_pump_glib.h',
- 'message_pump_glib_x.cc',
- 'message_pump_glib_x.h',
- 'message_pump_glib_x_dispatch.h',
- 'message_pump_libevent.cc',
- 'message_pump_libevent.h',
- 'message_pump_mac.h',
- 'message_pump_mac.mm',
- 'metrics/field_trial.cc',
- 'metrics/field_trial.h',
- 'nsimage_cache_mac.h',
- 'nsimage_cache_mac.mm',
- 'nss_util.cc',
- 'nss_util.h',
- 'openssl_util.cc',
- 'openssl_util.h',
- 'setproctitle_linux.c',
- 'setproctitle_linux.h',
- 'sha2.cc',
- 'sha2.h',
- 'sha2_openssl.cc',
- 'string16.cc',
- 'string16.h',
- 'sync_socket.h',
- 'sync_socket_win.cc',
- 'sync_socket_posix.cc',
- 'time_mac.cc',
- 'time_posix.cc',
- ],
- 'conditions': [
- [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', {
- 'conditions': [
- [ 'chromeos==1', {
- 'sources/': [ ['include', '_chromeos\\.cc$'] ]
- },
- ],
- ],
- 'defines': [
- 'USE_SYMBOLIZE',
- ],
- 'cflags': [
- '-Wno-write-strings',
- ],
- }, { # OS != "linux" and OS != "freebsd" and OS != "openbsd" and OS != "solaris"
- 'sources/': [
- ['exclude', '/xdg_user_dirs/'],
- ['exclude', '_nss\.cc$'],
- ],
- }],
- [ 'OS != "mac"', {
- 'sources!': [
- 'crypto/cssm_init.cc',
- 'crypto/cssm_init.h',
- ],
- },],
- [ 'OS != "win"', {
- 'sources!': [
- 'third_party/purify/pure_api.c',
- 'base_drag_source.cc',
- 'base_drop_target.cc',
- 'cpu.cc',
- 'crypto/capi_util.h',
- 'crypto/capi_util.cc',
- 'debug_on_start.cc',
- 'event_recorder.cc',
- 'file_version_info.cc',
- 'image_util.cc',
- 'object_watcher.cc',
- 'pe_image.cc',
- 'registry.cc',
- 'resource_util.cc',
- 'win_util.cc',
- ],
- },],
- [ 'use_openssl==1', {
- # TODO(joth): Use a glob to match exclude patterns once the
- # OpenSSL file set is complete.
- 'sources!': [
- 'crypto/encryptor_nss.cc',
- 'crypto/rsa_private_key_nss.cc',
- 'crypto/signature_creator_nss.cc',
- 'crypto/signature_verifier_nss.cc',
- 'crypto/symmetric_key_nss.cc',
- 'hmac_nss.cc',
- 'nss_util.cc',
- 'nss_util.h',
- # Note that sha2.cc depends on the NSS files bundled into
- # chromium; it does not have the _nss postfix as it is required
- # on platforms besides linux and *bsd.
- 'sha2.cc',
- 'third_party/nss/blapi.h',
- 'third_party/nss/blapit.h',
- 'third_party/nss/sha256.h',
- 'third_party/nss/sha512.cc',
- ],
- }, {
- 'sources!': [
- 'crypto/encryptor_openssl.cc',
- 'crypto/rsa_private_key_openssl.cc',
- 'crypto/signature_creator_openssl.cc',
- 'crypto/signature_verifier_openssl.cc',
- 'crypto/symmetric_key_openssl.cc',
- 'hmac_openssl.cc',
- 'openssl_util.cc',
- 'openssl_util.h',
- 'sha2_openssl.cc',
- ],
- },],
- ],
- }],
],
},
'targets': [
@@ -589,7 +402,6 @@
'msvs_guid': '1832A374-8A74-4F9E-B536-69A699B3E165',
'variables': {
'base_target': 1,
- 'base_extra_target': 1,
},
'dependencies': [
'../third_party/modp_b64/modp_b64.gyp:modp_b64',
@@ -603,8 +415,12 @@
],
},
'conditions': [
- [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd"', {
+ [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', {
'conditions': [
+ [ 'chromeos==1', {
+ 'sources/': [ ['include', '_chromeos\\.cc$'] ]
+ },
+ ],
[ 'linux_use_tcmalloc==0', {
'defines': [
'NO_TCMALLOC',
@@ -618,7 +434,7 @@
],
[ 'use_openssl==1', {
'dependencies': [
- '../build/linux/system.gyp:openssl',
+ '../third_party/openssl/openssl.gyp:openssl',
],
}, { # use_openssl==0
'dependencies': [
@@ -634,11 +450,22 @@
'../build/linux/system.gyp:x11',
'xdg_mime',
],
+ 'defines': [
+ 'USE_SYMBOLIZE',
+ ],
+ 'cflags': [
+ '-Wno-write-strings',
+ ],
'export_dependent_settings': [
'../build/linux/system.gyp:gtk',
'../build/linux/system.gyp:x11',
],
- },],
+ }, { # OS != "linux" and OS != "freebsd" and OS != "openbsd" and OS != "solaris"
+ 'sources/': [
+ ['exclude', '/xdg_user_dirs/'],
+ ['exclude', '_nss\.cc$'],
+ ],
+ }],
[ 'OS == "freebsd" or OS == "openbsd"', {
'link_settings': {
'libraries': [
@@ -668,7 +495,12 @@
'$(SDKROOT)/System/Library/Frameworks/Security.framework',
],
},
- },],
+ }, { # OS != "mac"
+ 'sources!': [
+ 'crypto/cssm_init.cc',
+ 'crypto/cssm_init.h',
+ ],
+ }],
[ 'OS == "mac" or OS == "win"', {
'dependencies': [
'../third_party/nss/nss.gyp:nss',
@@ -676,8 +508,145 @@
},],
[ 'OS != "win"', {
'dependencies': ['../third_party/libevent/libevent.gyp:libevent'],
+ 'sources!': [
+ 'third_party/purify/pure_api.c',
+ 'base_drag_source.cc',
+ 'base_drop_target.cc',
+ 'cpu.cc',
+ 'crypto/capi_util.h',
+ 'crypto/capi_util.cc',
+ 'debug_on_start.cc',
+ 'event_recorder.cc',
+ 'file_version_info.cc',
+ 'object_watcher.cc',
+ 'pe_image.cc',
+ 'registry.cc',
+ 'resource_util.cc',
+ 'win_util.cc',
+ ],
+ },],
+ [ 'use_openssl==1', {
+ # TODO(joth): Use a glob to match exclude patterns once the
+ # OpenSSL file set is complete.
+ 'sources!': [
+ 'crypto/encryptor_nss.cc',
+ 'crypto/rsa_private_key_nss.cc',
+ 'crypto/signature_creator_nss.cc',
+ 'crypto/signature_verifier_nss.cc',
+ 'crypto/symmetric_key_nss.cc',
+ 'hmac_nss.cc',
+ 'nss_util.cc',
+ 'nss_util.h',
+ # Note that sha2.cc depends on the NSS files bundled into
+ # chromium; it does not have the _nss postfix as it is required
+ # on platforms besides linux and *bsd.
+ 'sha2.cc',
+ 'third_party/nss/blapi.h',
+ 'third_party/nss/blapit.h',
+ 'third_party/nss/sha256.h',
+ 'third_party/nss/sha512.cc',
+ ],
+ }, {
+ 'sources!': [
+ 'crypto/encryptor_openssl.cc',
+ 'crypto/rsa_private_key_openssl.cc',
+ 'crypto/signature_creator_openssl.cc',
+ 'crypto/signature_verifier_openssl.cc',
+ 'crypto/symmetric_key_openssl.cc',
+ 'hmac_openssl.cc',
+ 'openssl_util.cc',
+ 'openssl_util.h',
+ 'sha2_openssl.cc',
+ ],
},],
],
+ 'sources': [
+ 'crypto/capi_util.cc',
+ 'crypto/capi_util.h',
+ 'crypto/cssm_init.cc',
+ 'crypto/cssm_init.h',
+ 'crypto/encryptor.h',
+ 'crypto/encryptor_mac.cc',
+ 'crypto/encryptor_nss.cc',
+ 'crypto/encryptor_openssl.cc',
+ 'crypto/encryptor_win.cc',
+ 'crypto/rsa_private_key.h',
+ 'crypto/rsa_private_key.cc',
+ 'crypto/rsa_private_key_mac.cc',
+ 'crypto/rsa_private_key_nss.cc',
+ 'crypto/rsa_private_key_openssl.cc',
+ 'crypto/rsa_private_key_win.cc',
+ 'crypto/signature_creator.h',
+ 'crypto/signature_creator_mac.cc',
+ 'crypto/signature_creator_nss.cc',
+ 'crypto/signature_creator_openssl.cc',
+ 'crypto/signature_creator_win.cc',
+ 'crypto/signature_verifier.h',
+ 'crypto/signature_verifier_mac.cc',
+ 'crypto/signature_verifier_nss.cc',
+ 'crypto/signature_verifier_openssl.cc',
+ 'crypto/signature_verifier_win.cc',
+ 'crypto/symmetric_key.h',
+ 'crypto/symmetric_key_mac.cc',
+ 'crypto/symmetric_key_nss.cc',
+ 'crypto/symmetric_key_openssl.cc',
+ 'crypto/symmetric_key_win.cc',
+ 'third_party/nspr/prcpucfg.h',
+ 'third_party/nspr/prcpucfg_win.h',
+ 'third_party/nspr/prtypes.h',
+ 'third_party/nss/blapi.h',
+ 'third_party/nss/blapit.h',
+ 'third_party/nss/sha256.h',
+ 'third_party/nss/sha512.cc',
+ 'third_party/purify/pure.h',
+ 'third_party/purify/pure_api.c',
+ 'third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
+ 'third_party/xdg_user_dirs/xdg_user_dir_lookup.h',
+ 'auto_reset.h',
+ 'base64.cc',
+ 'base64.h',
+ 'event_recorder.cc',
+ 'event_recorder.h',
+ 'event_recorder_stubs.cc',
+ 'file_descriptor_shuffle.cc',
+ 'file_descriptor_shuffle.h',
+ 'hmac.h',
+ 'hmac_mac.cc',
+ 'hmac_nss.cc',
+ 'hmac_openssl.cc',
+ 'hmac_win.cc',
+ 'linux_util.cc',
+ 'linux_util.h',
+ 'md5.cc',
+ 'md5.h',
+ 'message_pump_glib.cc',
+ 'message_pump_glib.h',
+ 'message_pump_glib_x.cc',
+ 'message_pump_glib_x.h',
+ 'message_pump_glib_x_dispatch.h',
+ 'message_pump_libevent.cc',
+ 'message_pump_libevent.h',
+ 'message_pump_mac.h',
+ 'message_pump_mac.mm',
+ 'metrics/field_trial.cc',
+ 'metrics/field_trial.h',
+ 'nss_util.cc',
+ 'nss_util.h',
+ 'openssl_util.cc',
+ 'openssl_util.h',
+ 'setproctitle_linux.c',
+ 'setproctitle_linux.h',
+ 'sha2.cc',
+ 'sha2.h',
+ 'sha2_openssl.cc',
+ 'string16.cc',
+ 'string16.h',
+ 'sync_socket.h',
+ 'sync_socket_win.cc',
+ 'sync_socket_posix.cc',
+ 'time_mac.cc',
+ 'time_posix.cc',
+ ],
},
],
'conditions': [
@@ -714,59 +683,6 @@
},
],
}],
- [ 'OS == "linux" and internal_pdf', {
- 'targets': [
- {
- 'target_name': 'base_fpic',
- 'type': '<(library)',
- 'variables': {
- 'base_target': 1,
- 'base_extra_target': 1,
- },
- 'cflags': [
- '-fPIC',
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '..',
- ],
- },
- 'conditions': [
- [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd"', {
- 'dependencies': [
- '../build/util/build_util.gyp:lastchange',
- '../build/linux/system.gyp:gtk',
- '../build/linux/system.gyp:nss',
- '../build/linux/system.gyp:x11',
- 'xdg_mime',
- ],
- 'export_dependent_settings': [
- '../build/linux/system.gyp:gtk',
- '../build/linux/system.gyp:x11',
- ],
- },],
- ['OS == "linux"', {
- 'link_settings': {
- 'libraries': [
- # We need rt for clock_gettime().
- '-lrt',
- # For 'native_library_linux.cc'
- '-ldl',
- ],
- },
- }],
- [ 'OS == "mac" or OS == "win"', {
- 'dependencies': [
- '../third_party/nss/nss.gyp:nss',
- ],
- },],
- [ 'OS != "win"', {
- 'dependencies': ['../third_party/libevent/libevent.gyp:libevent'],
- },],
- ],
- },
- ],
- }],
[ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', {
'targets': [
{
diff --git a/base/base_paths_linux.cc b/base/base_paths_linux.cc
index b2f2b57..48db3f8 100644
--- a/base/base_paths_linux.cc
+++ b/base/base_paths_linux.cc
@@ -37,14 +37,12 @@ bool PathProviderPosix(int key, FilePath* result) {
case base::FILE_EXE:
case base::FILE_MODULE: { // TODO(evanm): is this correct?
#if defined(OS_LINUX)
- char bin_dir[PATH_MAX + 1];
- int bin_dir_size = readlink(kSelfExe, bin_dir, PATH_MAX);
- if (bin_dir_size < 0 || bin_dir_size > PATH_MAX) {
+ FilePath bin_dir;
+ if (!file_util::ReadSymbolicLink(FilePath(kSelfExe), &bin_dir)) {
NOTREACHED() << "Unable to resolve " << kSelfExe << ".";
return false;
}
- bin_dir[bin_dir_size] = 0;
- *result = FilePath(bin_dir);
+ *result = bin_dir;
return true;
#elif defined(OS_FREEBSD)
int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
@@ -76,7 +74,7 @@ bool PathProviderPosix(int key, FilePath* result) {
}
}
// On POSIX, unit tests execute two levels deep from the source root.
- // For example: sconsbuild/{Debug|Release}/net_unittest
+ // For example: out/{Debug|Release}/net_unittest
if (PathService::Get(base::DIR_EXE, &path)) {
path = path.DirName().DirName();
if (file_util::PathExists(path.Append(kThisSourceFile))) {
diff --git a/base/callback.h b/base/callback.h
index 7f2eb70..e5ea771 100644
--- a/base/callback.h
+++ b/base/callback.h
@@ -206,8 +206,9 @@ template <class T, class Method, class Params>
class UnboundMethod {
public:
UnboundMethod(Method m, const Params& p) : m_(m), p_(p) {
- COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
- badunboundmethodparams);
+ COMPILE_ASSERT(
+ (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
+ badunboundmethodparams);
}
void Run(T* obj) const {
DispatchToMethod(obj, m_, p_);
diff --git a/base/chrome_application_mac.h b/base/chrome_application_mac.h
deleted file mode 100644
index 676959e..0000000
--- a/base/chrome_application_mac.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2009 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_CHROME_APPLICATION_MAC_H_
-#define BASE_CHROME_APPLICATION_MAC_H_
-#pragma once
-
-#import <AppKit/AppKit.h>
-
-#include "base/basictypes.h"
-#include "base/scoped_nsobject.h"
-
-// Event hooks must implement this protocol.
-@protocol CrApplicationEventHookProtocol
-- (void)hookForEvent:(NSEvent*)theEvent;
-@end
-
-
-@interface CrApplication : NSApplication {
- @private
- BOOL handlingSendEvent_;
- // Array of objects implementing the CrApplicationEventHookProtocol
- scoped_nsobject<NSMutableArray> eventHooks_;
-}
-@property(readonly,
- getter=isHandlingSendEvent,
- nonatomic) BOOL handlingSendEvent;
-
-// Add or remove an event hook to be called for every sendEvent:
-// that the application receives. These handlers are called before
-// the normal [NSApplication sendEvent:] call is made.
-
-// This is not a good alternative to a nested event loop. It should
-// be used only when normal event logic and notification breaks down
-// (e.g. when clicking outside a canBecomeKey:NO window to "switch
-// context" out of it).
-- (void)addEventHook:(id<CrApplicationEventHookProtocol>)hook;
-- (void)removeEventHook:(id<CrApplicationEventHookProtocol>)hook;
-
-+ (NSApplication*)sharedApplication;
-@end
-
-namespace chrome_application_mac {
-
-// Controls the state of |handlingSendEvent_| in the event loop so that it is
-// reset properly.
-class ScopedSendingEvent {
- public:
- ScopedSendingEvent();
- ~ScopedSendingEvent();
-
- private:
- CrApplication* app_;
- BOOL handling_;
- DISALLOW_COPY_AND_ASSIGN(ScopedSendingEvent);
-};
-
-} // chrome_application_mac
-
-#endif // BASE_CHROME_APPLICATION_MAC_H_
diff --git a/base/chrome_application_mac.mm b/base/chrome_application_mac.mm
deleted file mode 100644
index a163534..0000000
--- a/base/chrome_application_mac.mm
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2009 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 "chrome_application_mac.h"
-
-#include "base/logging.h"
-
-@interface CrApplication ()
-@property(readwrite,
- getter=isHandlingSendEvent,
- nonatomic) BOOL handlingSendEvent;
-@end
-
-@implementation CrApplication
-@synthesize handlingSendEvent = handlingSendEvent_;
-
-// Initialize NSApplication using the custom subclass. Check whether NSApp
-// was already initialized using another class, because that would break
-// some things.
-+ (NSApplication*)sharedApplication {
- NSApplication* app = [super sharedApplication];
- if (![NSApp isKindOfClass:self]) {
- LOG(ERROR) << "NSApp should be of type " << [[self className] UTF8String]
- << ", not " << [[NSApp className] UTF8String];
- DCHECK(false) << "NSApp is of wrong type";
- }
- return app;
-}
-
-- (id)init {
- if ((self = [super init])) {
- eventHooks_.reset([[NSMutableArray alloc] init]);
- }
- return self;
-}
-
-- (void)sendEvent:(NSEvent*)event {
- chrome_application_mac::ScopedSendingEvent sendingEventScoper;
- for (id<CrApplicationEventHookProtocol> handler in eventHooks_.get()) {
- [handler hookForEvent:event];
- }
- [super sendEvent:event];
-}
-
-- (void)addEventHook:(id<CrApplicationEventHookProtocol>)handler {
- [eventHooks_ addObject:handler];
-}
-
-- (void)removeEventHook:(id<CrApplicationEventHookProtocol>)handler {
- [eventHooks_ removeObject:handler];
-}
-
-@end
-
-namespace chrome_application_mac {
-
-ScopedSendingEvent::ScopedSendingEvent()
- : app_(static_cast<CrApplication*>([CrApplication sharedApplication])),
- handling_([app_ isHandlingSendEvent]) {
- [app_ setHandlingSendEvent:YES];
-}
-
-ScopedSendingEvent::~ScopedSendingEvent() {
- [app_ setHandlingSendEvent:handling_];
-}
-
-} // namespace chrome_application_mac
diff --git a/base/command_line.cc b/base/command_line.cc
index b335e7c..70d6872 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -19,6 +19,7 @@
#include <algorithm>
#include "base/file_path.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_split.h"
@@ -237,13 +238,11 @@ void CommandLine::SetProcTitle() {
// show up as "exe" in process listings. Read the symlink /proc/self/exe and
// use the path it points at for our process title. Note that this is only for
// display purposes and has no TOCTTOU security implications.
- char buffer[PATH_MAX];
- // Note: readlink() does not append a null byte to terminate the string.
- ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
- DCHECK(length <= static_cast<ssize_t>(sizeof(buffer)));
- if (length > 0) {
+ FilePath target;
+ FilePath self_exe("/proc/self/exe");
+ if (file_util::ReadSymbolicLink(self_exe, &target)) {
have_argv0 = true;
- title.assign(buffer, length);
+ title = target.value();
// If the binary has since been deleted, Linux appends " (deleted)" to the
// symlink target. Remove it, since this is not really part of our name.
const std::string kDeletedSuffix = " (deleted)";
@@ -288,13 +287,6 @@ bool CommandLine::HasSwitch(const std::string& switch_string) const {
return switches_.find(lowercased_switch) != switches_.end();
}
-#if defined(OS_WIN)
-// Deprecated; still temporarily available on Windows.
-bool CommandLine::HasSwitch(const std::wstring& switch_string) const {
- return HasSwitch(WideToASCII(switch_string));
-}
-#endif
-
std::string CommandLine::GetSwitchValueASCII(
const std::string& switch_string) const {
CommandLine::StringType value = GetSwitchValueNative(switch_string);
diff --git a/base/command_line.h b/base/command_line.h
index a5bdd1a..df0293c 100644
--- a/base/command_line.h
+++ b/base/command_line.h
@@ -161,13 +161,6 @@ class CommandLine {
void CopySwitchesFrom(const CommandLine& source, const char* const switches[],
size_t count);
- // APIs that work with wstrings are deprecated.
- // TODO(evanm): remove all of these.
-#if defined(OS_WIN)
- // Deprecated on non-Windows.
- bool HasSwitch(const std::wstring& switch_string) const;
-#endif
-
private:
friend class InProcessBrowserTest;
diff --git a/base/crypto/cssm_init.cc b/base/crypto/cssm_init.cc
index b04cbe7..46a6ffe 100644
--- a/base/crypto/cssm_init.cc
+++ b/base/crypto/cssm_init.cc
@@ -22,6 +22,13 @@ namespace {
class CSSMInitSingleton {
public:
+ static CSSMInitSingleton* GetInstance() {
+ return Singleton<CSSMInitSingleton>::get();
+ }
+
+ CSSM_CSP_HANDLE csp_handle() const {return csp_handle_;}
+
+ private:
CSSMInitSingleton() : inited_(false), loaded_(false), csp_handle_(NULL) {
static CSSM_VERSION version = {2, 0};
// TODO(wtc): what should our caller GUID be?
@@ -68,18 +75,21 @@ class CSSMInitSingleton {
}
}
- CSSM_CSP_HANDLE csp_handle() const {return csp_handle_;}
-
- private:
bool inited_; // True if CSSM_Init has been called successfully.
bool loaded_; // True if CSSM_ModuleLoad has been called successfully.
CSSM_CSP_HANDLE csp_handle_;
+
+ friend struct DefaultSingletonTraits<CSSMInitSingleton>;
};
// This singleton is separate as it pertains to Apple's wrappers over
// their own CSSM handles, as opposed to our own CSSM_CSP_HANDLE.
class SecurityServicesSingleton {
public:
+ static SecurityServicesSingleton* GetInstance() {
+ return Singleton<SecurityServicesSingleton>::get();
+ }
+
~SecurityServicesSingleton() {}
Lock& lock() { return lock_; }
@@ -100,11 +110,11 @@ class SecurityServicesSingleton {
namespace base {
void EnsureCSSMInit() {
- Singleton<CSSMInitSingleton>::get();
+ CSSMInitSingleton::GetInstance();
}
CSSM_CSP_HANDLE GetSharedCSPHandle() {
- return Singleton<CSSMInitSingleton>::get()->csp_handle();
+ return CSSMInitSingleton::GetInstance()->csp_handle();
}
void* CSSMMalloc(CSSM_SIZE size, void *alloc_ref) {
@@ -145,7 +155,7 @@ void LogCSSMError(const char *fn_name, CSSM_RETURN err) {
}
Lock& GetMacSecurityServicesLock() {
- return Singleton<SecurityServicesSingleton>::get()->lock();
+ return SecurityServicesSingleton::GetInstance()->lock();
}
} // namespace base
diff --git a/base/crypto/rsa_private_key.h b/base/crypto/rsa_private_key.h
index ecec015..bac4250 100644
--- a/base/crypto/rsa_private_key.h
+++ b/base/crypto/rsa_private_key.h
@@ -165,6 +165,7 @@ class PrivateKeyInfoCodec {
// Encapsulates an RSA private key. Can be used to generate new keys, export
// keys to other formats, or to extract a public key.
+// TODO(hclam): This class should be ref-counted so it can be reused easily.
class RSAPrivateKey {
public:
// Create a new random instance. Can return NULL if initialization fails.
@@ -208,6 +209,7 @@ class RSAPrivateKey {
EVP_PKEY* key() { return key_; }
#elif defined(USE_NSS)
SECKEYPrivateKeyStr* key() { return key_; }
+ SECKEYPublicKeyStr* public_key() { return public_key_; }
#elif defined(OS_WIN)
HCRYPTPROV provider() { return provider_; }
HCRYPTKEY key() { return key_; }
diff --git a/base/crypto/rsa_private_key_openssl.cc b/base/crypto/rsa_private_key_openssl.cc
index 0776b63..891ea52 100644
--- a/base/crypto/rsa_private_key_openssl.cc
+++ b/base/crypto/rsa_private_key_openssl.cc
@@ -50,9 +50,13 @@ bool ExportKey(EVP_PKEY* key,
// static
RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<RSA, RSA_free> rsa_key(RSA_generate_key(num_bits, 65537L,
- NULL, NULL));
- if (!rsa_key.get())
+
+ ScopedOpenSSL<RSA, RSA_free> rsa_key(RSA_new());
+ ScopedOpenSSL<BIGNUM, BN_free> bn(BN_new());
+ if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
+ return NULL;
+
+ if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL))
return NULL;
scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
@@ -75,7 +79,8 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
OpenSSLErrStackTracer err_tracer(FROM_HERE);
// BIO_new_mem_buf is not const aware, but it does not modify the buffer.
- char* data = reinterpret_cast<char*>(const_cast<uint8*>(input.data()));
+ char* data = reinterpret_cast<char*>(const_cast<uint8*>(
+ vector_as_array(&input)));
ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, input.size()));
if (!bio.get())
return NULL;
diff --git a/base/crypto/signature_creator_openssl.cc b/base/crypto/signature_creator_openssl.cc
index 7eed379..5bdb783 100644
--- a/base/crypto/signature_creator_openssl.cc
+++ b/base/crypto/signature_creator_openssl.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/openssl_util.h"
#include "base/scoped_ptr.h"
+#include "base/stl_util-inl.h"
namespace base {
@@ -41,7 +42,7 @@ bool SignatureCreator::Final(std::vector<uint8>* signature) {
signature->resize(EVP_PKEY_size(key));
unsigned int len = 0;
- int rv = EVP_SignFinal(sign_context_, signature->data(), &len, key);
+ int rv = EVP_SignFinal(sign_context_, vector_as_array(signature), &len, key);
if (!rv) {
signature->clear();
return false;
diff --git a/base/crypto/signature_verifier_openssl.cc b/base/crypto/signature_verifier_openssl.cc
index b4fff78..4850efa 100644
--- a/base/crypto/signature_verifier_openssl.cc
+++ b/base/crypto/signature_verifier_openssl.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/openssl_util.h"
#include "base/scoped_ptr.h"
+#include "base/stl_util-inl.h"
namespace base {
@@ -77,7 +78,7 @@ bool SignatureVerifier::VerifyFinal() {
DCHECK(verify_context_);
OpenSSLErrStackTracer err_tracer(FROM_HERE);
int rv = EVP_VerifyFinal(verify_context_->ctx.get(),
- signature_.data(), signature_.size(),
+ vector_as_array(&signature_), signature_.size(),
verify_context_->public_key.get());
DCHECK_GE(rv, 0);
Reset();
diff --git a/base/data/data_pack_unittest/sample.pak b/base/data/data_pack_unittest/sample.pak
deleted file mode 100644
index fdbe2b5..0000000
--- a/base/data/data_pack_unittest/sample.pak
+++ /dev/null
Binary files differ
diff --git a/base/data_pack.cc b/base/data_pack.cc
deleted file mode 100644
index e01318f..0000000
--- a/base/data_pack.cc
+++ /dev/null
@@ -1,216 +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/data_pack.h"
-
-#include <errno.h>
-
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "base/ref_counted_memory.h"
-#include "base/string_piece.h"
-
-// For details of the file layout, see
-// http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
-
-namespace {
-
-// A word is four bytes.
-static const size_t kWord = 4;
-
-static const uint32 kFileFormatVersion = 1;
-// Length of file header: version and entry count.
-static const size_t kHeaderLength = 2 * sizeof(uint32);
-
-struct DataPackEntry {
- uint32 resource_id;
- uint32 file_offset;
- uint32 length;
-
- static int CompareById(const void* void_key, const void* void_entry) {
- uint32 key = *reinterpret_cast<const uint32*>(void_key);
- const DataPackEntry* entry =
- reinterpret_cast<const DataPackEntry*>(void_entry);
- if (key < entry->resource_id) {
- return -1;
- } else if (key > entry->resource_id) {
- return 1;
- } else {
- return 0;
- }
- }
-};
-
-COMPILE_ASSERT(sizeof(DataPackEntry) == 12, size_of_header_must_be_twelve);
-
-// We're crashing when trying to load a pak file on Windows. Add some error
-// codes for logging.
-// http://crbug.com/58056
-enum LoadErrors {
- INIT_FAILED = 1,
- BAD_VERSION,
- INDEX_TRUNCATED,
- ENTRY_NOT_FOUND,
-
- LOAD_ERRORS_COUNT,
-};
-
-} // anonymous namespace
-
-namespace base {
-
-// In .cc for MemoryMappedFile dtor.
-DataPack::DataPack() : resource_count_(0) {
-}
-DataPack::~DataPack() {
-}
-
-bool DataPack::Load(const FilePath& path) {
- mmap_.reset(new file_util::MemoryMappedFile);
- if (!mmap_->Initialize(path)) {
- DLOG(ERROR) << "Failed to mmap datapack";
- UMA_HISTOGRAM_ENUMERATION("DataPack.Load", INIT_FAILED,
- LOAD_ERRORS_COUNT);
- return false;
- }
-
- // Parse the header of the file.
- // First uint32: version; second: resource count.
- const uint32* ptr = reinterpret_cast<const uint32*>(mmap_->data());
- uint32 version = ptr[0];
- if (version != kFileFormatVersion) {
- LOG(ERROR) << "Bad data pack version: got " << version << ", expected "
- << kFileFormatVersion;
- UMA_HISTOGRAM_ENUMERATION("DataPack.Load", BAD_VERSION,
- LOAD_ERRORS_COUNT);
- mmap_.reset();
- return false;
- }
- resource_count_ = ptr[1];
-
- // Sanity check the file.
- // 1) Check we have enough entries.
- if (kHeaderLength + resource_count_ * sizeof(DataPackEntry) >
- mmap_->length()) {
- LOG(ERROR) << "Data pack file corruption: too short for number of "
- "entries specified.";
- UMA_HISTOGRAM_ENUMERATION("DataPack.Load", INDEX_TRUNCATED,
- LOAD_ERRORS_COUNT);
- mmap_.reset();
- return false;
- }
- // 2) Verify the entries are within the appropriate bounds.
- for (size_t i = 0; i < resource_count_; ++i) {
- const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>(
- mmap_->data() + kHeaderLength + (i * sizeof(DataPackEntry)));
- if (entry->file_offset + entry->length > mmap_->length()) {
- LOG(ERROR) << "Entry #" << i << " in data pack points off end of file. "
- << "Was the file corrupted?";
- UMA_HISTOGRAM_ENUMERATION("DataPack.Load", ENTRY_NOT_FOUND,
- LOAD_ERRORS_COUNT);
- mmap_.reset();
- return false;
- }
- }
-
- return true;
-}
-
-bool DataPack::GetStringPiece(uint32 resource_id, StringPiece* data) const {
- // It won't be hard to make this endian-agnostic, but it's not worth
- // bothering to do right now.
-#if defined(__BYTE_ORDER)
- // Linux check
- COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN,
- datapack_assumes_little_endian);
-#elif defined(__BIG_ENDIAN__)
- // Mac check
- #error DataPack assumes little endian
-#endif
-
- DataPackEntry* target = reinterpret_cast<DataPackEntry*>(
- bsearch(&resource_id, mmap_->data() + kHeaderLength, resource_count_,
- sizeof(DataPackEntry), DataPackEntry::CompareById));
- if (!target) {
- return false;
- }
-
- data->set(mmap_->data() + target->file_offset, target->length);
- return true;
-}
-
-RefCountedStaticMemory* DataPack::GetStaticMemory(uint32 resource_id) const {
- base::StringPiece piece;
- if (!GetStringPiece(resource_id, &piece))
- return NULL;
-
- return new RefCountedStaticMemory(
- reinterpret_cast<const unsigned char*>(piece.data()), piece.length());
-}
-
-// static
-bool DataPack::WritePack(const FilePath& path,
- const std::map<uint32, StringPiece>& resources) {
- FILE* file = file_util::OpenFile(path, "wb");
- if (!file)
- return false;
-
- if (fwrite(&kFileFormatVersion, 1, kWord, file) != kWord) {
- LOG(ERROR) << "Failed to write file version";
- file_util::CloseFile(file);
- return false;
- }
-
- // Note: the python version of this function explicitly sorted keys, but
- // std::map is a sorted associative container, we shouldn't have to do that.
- uint32 entry_count = resources.size();
- if (fwrite(&entry_count, 1, kWord, file) != kWord) {
- LOG(ERROR) << "Failed to write entry count";
- file_util::CloseFile(file);
- return false;
- }
-
- // Each entry is 3 uint32s.
- uint32 index_length = entry_count * 3 * kWord;
- uint32 data_offset = kHeaderLength + index_length;
- for (std::map<uint32, StringPiece>::const_iterator it = resources.begin();
- it != resources.end(); ++it) {
- if (fwrite(&it->first, 1, kWord, file) != kWord) {
- LOG(ERROR) << "Failed to write id for " << it->first;
- file_util::CloseFile(file);
- return false;
- }
-
- if (fwrite(&data_offset, 1, kWord, file) != kWord) {
- LOG(ERROR) << "Failed to write offset for " << it->first;
- file_util::CloseFile(file);
- return false;
- }
-
- uint32 len = it->second.length();
- if (fwrite(&len, 1, kWord, file) != kWord) {
- LOG(ERROR) << "Failed to write length for " << it->first;
- file_util::CloseFile(file);
- return false;
- }
-
- data_offset += len;
- }
-
- for (std::map<uint32, StringPiece>::const_iterator it = resources.begin();
- it != resources.end(); ++it) {
- if (fwrite(it->second.data(), it->second.length(), 1, file) != 1) {
- LOG(ERROR) << "Failed to write data for " << it->first;
- file_util::CloseFile(file);
- return false;
- }
- }
-
- file_util::CloseFile(file);
-
- return true;
-}
-
-} // namespace base
diff --git a/base/data_pack.h b/base/data_pack.h
deleted file mode 100644
index 2836715..0000000
--- a/base/data_pack.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2008 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.
-
-// DataPack represents a read-only view onto an on-disk file that contains
-// (key, value) pairs of data. It's used to store static resources like
-// translation strings and images.
-
-#ifndef BASE_DATA_PACK_H_
-#define BASE_DATA_PACK_H_
-#pragma once
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-
-namespace file_util {
- class MemoryMappedFile;
-}
-class FilePath;
-class RefCountedStaticMemory;
-
-namespace base {
-
-class StringPiece;
-
-class DataPack {
- public:
- DataPack();
- ~DataPack();
-
- // Load a pack file from |path|, returning false on error.
- bool Load(const FilePath& path);
-
- // Get resource by id |resource_id|, filling in |data|.
- // The data is owned by the DataPack object and should not be modified.
- // Returns false if the resource id isn't found.
- bool GetStringPiece(uint32 resource_id, StringPiece* data) const;
-
- // Like GetStringPiece(), but returns a reference to memory. This interface
- // is used for image data, while the StringPiece interface is usually used
- // for localization strings.
- RefCountedStaticMemory* GetStaticMemory(uint32 resource_id) const;
-
- // Writes a pack file containing |resources| to |path|.
- static bool WritePack(const FilePath& path,
- const std::map<uint32, StringPiece>& resources);
-
- private:
- // The memory-mapped data.
- scoped_ptr<file_util::MemoryMappedFile> mmap_;
-
- // Number of resources in the data.
- size_t resource_count_;
-
- DISALLOW_COPY_AND_ASSIGN(DataPack);
-};
-
-} // namespace base
-
-#endif // BASE_DATA_PACK_H_
diff --git a/base/data_pack_unittest.cc b/base/data_pack_unittest.cc
deleted file mode 100644
index d089b28..0000000
--- a/base/data_pack_unittest.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2008 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/data_pack.h"
-
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/scoped_temp_dir.h"
-#include "base/string_piece.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(DataPackTest, Load) {
- FilePath data_path;
- PathService::Get(base::DIR_SOURCE_ROOT, &data_path);
- data_path = data_path.Append(
- FILE_PATH_LITERAL("base/data/data_pack_unittest/sample.pak"));
-
- base::DataPack pack;
- ASSERT_TRUE(pack.Load(data_path));
-
- base::StringPiece data;
- ASSERT_TRUE(pack.GetStringPiece(4, &data));
- EXPECT_EQ("this is id 4", data);
- ASSERT_TRUE(pack.GetStringPiece(6, &data));
- EXPECT_EQ("this is id 6", data);
-
- // Try reading zero-length data blobs, just in case.
- ASSERT_TRUE(pack.GetStringPiece(1, &data));
- EXPECT_EQ(0U, data.length());
- ASSERT_TRUE(pack.GetStringPiece(10, &data));
- EXPECT_EQ(0U, data.length());
-
- // Try looking up an invalid key.
- ASSERT_FALSE(pack.GetStringPiece(140, &data));
-}
-
-TEST(DataPackTest, Write) {
- ScopedTempDir dir;
- ASSERT_TRUE(dir.CreateUniqueTempDir());
- FilePath file = dir.path().Append(FILE_PATH_LITERAL("data.pak"));
-
- std::string one("one");
- std::string two("two");
- std::string three("three");
- std::string four("four");
- std::string fifteen("fifteen");
-
- std::map<uint32, base::StringPiece> resources;
- resources.insert(std::make_pair(1, base::StringPiece(one)));
- resources.insert(std::make_pair(2, base::StringPiece(two)));
- resources.insert(std::make_pair(15, base::StringPiece(fifteen)));
- resources.insert(std::make_pair(3, base::StringPiece(three)));
- resources.insert(std::make_pair(4, base::StringPiece(four)));
- ASSERT_TRUE(base::DataPack::WritePack(file, resources));
-
- // Now try to read the data back in.
- base::DataPack pack;
- ASSERT_TRUE(pack.Load(file));
-
- base::StringPiece data;
- ASSERT_TRUE(pack.GetStringPiece(1, &data));
- EXPECT_EQ(one, data);
- ASSERT_TRUE(pack.GetStringPiece(2, &data));
- EXPECT_EQ(two, data);
- ASSERT_TRUE(pack.GetStringPiece(3, &data));
- EXPECT_EQ(three, data);
- ASSERT_TRUE(pack.GetStringPiece(4, &data));
- EXPECT_EQ(four, data);
- ASSERT_TRUE(pack.GetStringPiece(15, &data));
- EXPECT_EQ(fifteen, data);
-}
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc
index 2df3c4c..1e0c2ba 100644
--- a/base/debug/debugger_posix.cc
+++ b/base/debug/debugger_posix.cc
@@ -3,13 +3,16 @@
// found in the LICENSE file.
#include "base/debug/debugger.h"
+#include "build/build_config.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
+#if !defined(OS_NACL)
#include <sys/sysctl.h>
+#endif
#include <sys/types.h>
#include <unistd.h>
@@ -125,6 +128,13 @@ bool BeingDebugged() {
return pid_index < status.size() && status[pid_index] != '0';
}
+#elif defined(OS_NACL)
+
+bool BeingDebugged() {
+ NOTIMPLEMENTED();
+ return false;
+}
+
#elif defined(OS_FREEBSD)
bool DebugUtil::BeingDebugged() {
@@ -151,6 +161,11 @@ bool DebugUtil::BeingDebugged() {
#if defined(NDEBUG) && !defined(OS_MACOSX)
#define DEBUG_BREAK() abort()
+#elif defined(OS_NACL)
+// The NaCl verifier doesn't let use use int3. For now, we call abort(). We
+// should ask for advice from some NaCl experts about the optimum thing here.
+// http://code.google.com/p/nativeclient/issues/detail?id=645
+#define DEBUG_BREAK() abort()
#elif defined(ARCH_CPU_ARM_FAMILY)
#define DEBUG_BREAK() asm("bkpt 0")
#else
@@ -159,9 +174,6 @@ bool DebugUtil::BeingDebugged() {
void BreakDebugger() {
DEBUG_BREAK();
-#if defined(NDEBUG)
- _exit(1);
-#endif
}
} // namespace debug
diff --git a/base/debug/debugger_win.cc b/base/debug/debugger_win.cc
index 51a067e..d1d47cd 100644
--- a/base/debug/debugger_win.cc
+++ b/base/debug/debugger_win.cc
@@ -106,9 +106,6 @@ void BreakDebugger() {
if (DebugUtil::AreDialogsSuppressed())
_exit(1);
__debugbreak();
-#if defined(NDEBUG)
- _exit(1);
-#endif
}
} // namespace debug
diff --git a/base/debug/leak_tracker.h b/base/debug/leak_tracker.h
index 9709aa1..a8ea5f4 100644
--- a/base/debug/leak_tracker.h
+++ b/base/debug/leak_tracker.h
@@ -24,8 +24,8 @@
// before destroying that thread, one can check that there are no remaining
// instances of that class.
//
-// For example, to enable leak tracking for class URLRequest, start by
-// adding a member variable of type LeakTracker<URLRequest>.
+// For example, to enable leak tracking for class net::URLRequest, start by
+// adding a member variable of type LeakTracker<net::URLRequest>.
//
// class URLRequest {
// ...
@@ -34,11 +34,11 @@
// };
//
//
-// Next, when we believe all instances of URLRequest have been deleted:
+// Next, when we believe all instances of net::URLRequest have been deleted:
//
-// LeakTracker<URLRequest>::CheckForLeaks();
+// LeakTracker<net::URLRequest>::CheckForLeaks();
//
-// Should the check fail (because there are live instances of URLRequest),
+// Should the check fail (because there are live instances of net::URLRequest),
// then the allocation callstack for each leaked instances is dumped to
// the error log.
//
diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc
index 5d5d88d..90e302e 100644
--- a/base/debug/stack_trace_posix.cc
+++ b/base/debug/stack_trace_posix.cc
@@ -56,9 +56,9 @@ const char kSymbolCharacters[] =
#if !defined(USE_SYMBOLIZE)
// Demangles C++ symbols in the given text. Example:
//
-// "sconsbuild/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
+// "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
// =>
-// "sconsbuild/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
+// "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
void DemangleSymbols(std::string* text) {
#if defined(__GLIBCXX__)
diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc
index 653d234..6f4ad02 100644
--- a/base/debug/stack_trace_win.cc
+++ b/base/debug/stack_trace_win.cc
@@ -36,7 +36,7 @@ namespace {
// just ignore it.
class SymbolContext {
public:
- static SymbolContext* Get() {
+ static SymbolContext* GetInstance() {
// We use a leaky singleton because code may call this during process
// termination.
return
@@ -179,7 +179,7 @@ void StackTrace::PrintBacktrace() {
}
void StackTrace::OutputToStream(std::ostream* os) {
- SymbolContext* context = SymbolContext::Get();
+ SymbolContext* context = SymbolContext::GetInstance();
DWORD error = context->init_error();
if (error != ERROR_SUCCESS) {
(*os) << "Error initializing symbols (" << error
diff --git a/base/debug/trace_event.cc b/base/debug/trace_event.cc
index 616d7ca..9b9ed1f 100644
--- a/base/debug/trace_event.cc
+++ b/base/debug/trace_event.cc
@@ -49,15 +49,18 @@ TraceLog::~TraceLog() {
}
// static
+TraceLog* TraceLog::GetInstance() {
+ return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get();
+}
+
+// static
bool TraceLog::IsTracing() {
- TraceLog* trace = Singleton<TraceLog>::get();
- return trace->enabled_;
+ return TraceLog::GetInstance()->enabled_;
}
// static
bool TraceLog::StartTracing() {
- TraceLog* trace = Singleton<TraceLog>::get();
- return trace->Start();
+ return TraceLog::GetInstance()->Start();
}
bool TraceLog::Start() {
@@ -78,8 +81,7 @@ bool TraceLog::Start() {
// static
void TraceLog::StopTracing() {
- TraceLog* trace = Singleton<TraceLog>::get();
- return trace->Stop();
+ return TraceLog::GetInstance()->Stop();
}
void TraceLog::Stop() {
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
index 38b4d05..476f065 100644
--- a/base/debug/trace_event.h
+++ b/base/debug/trace_event.h
@@ -52,7 +52,7 @@
// Record that an event (of name, id) has begun. All BEGIN events should have
// corresponding END events with a matching (name, id).
#define TRACE_EVENT_BEGIN(name, id, extra) \
- Singleton<base::debug::TraceLog>::get()->Trace( \
+ base::debug::TraceLog::GetInstance()->Trace( \
name, \
base::debug::TraceLog::EVENT_BEGIN, \
reinterpret_cast<const void*>(id), \
@@ -63,7 +63,7 @@
// Record that an event (of name, id) has ended. All END events should have
// corresponding BEGIN events with a matching (name, id).
#define TRACE_EVENT_END(name, id, extra) \
- Singleton<base::debug::TraceLog>::get()->Trace( \
+ base::debug::TraceLog::GetInstance()->Trace( \
name, \
base::debug::TraceLog::EVENT_END, \
reinterpret_cast<const void*>(id), \
@@ -73,7 +73,7 @@
// Record that an event (of name, id) with no duration has happened.
#define TRACE_EVENT_INSTANT(name, id, extra) \
- Singleton<base::debug::TraceLog>::get()->Trace( \
+ base::debug::TraceLog::GetInstance()->Trace( \
name, \
base::debug::TraceLog::EVENT_INSTANT, \
reinterpret_cast<const void*>(id), \
@@ -96,6 +96,8 @@ class TraceLog {
EVENT_INSTANT
};
+ static TraceLog* GetInstance();
+
// Is tracing currently enabled.
static bool IsTracing();
// Start logging trace events.
diff --git a/base/debug/trace_event_win.cc b/base/debug/trace_event_win.cc
index 8405699..005ff62 100644
--- a/base/debug/trace_event_win.cc
+++ b/base/debug/trace_event_win.cc
@@ -31,8 +31,8 @@ TraceLog::TraceLog() : EtwTraceProvider(kChromeTraceProviderName) {
Register();
}
-TraceLog* TraceLog::Get() {
- return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog>>::get();
+TraceLog* TraceLog::GetInstance() {
+ return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get();
}
bool TraceLog::StartTracing() {
@@ -99,7 +99,7 @@ void TraceLog::Trace(const char* name,
const void* id,
const char* extra,
size_t extra_len) {
- TraceLog* provider = TraceLog::Get();
+ TraceLog* provider = TraceLog::GetInstance();
if (provider && provider->IsTracing()) {
// Compute the name & extra lengths if not supplied already.
if (name_len == -1)
diff --git a/base/debug/trace_event_win.h b/base/debug/trace_event_win.h
index dd3f512..a1c79ba 100644
--- a/base/debug/trace_event_win.h
+++ b/base/debug/trace_event_win.h
@@ -85,7 +85,7 @@ class TraceLog : public base::win::EtwTraceProvider {
// Retrieves the singleton.
// Note that this may return NULL post-AtExit processing.
- static TraceLog* Get();
+ static TraceLog* GetInstance();
// Returns true iff tracing is turned on.
bool IsTracing() {
diff --git a/base/debug/trace_event_win_unittest.cc b/base/debug/trace_event_win_unittest.cc
index 8544bc7..4c5ed45 100644
--- a/base/debug/trace_event_win_unittest.cc
+++ b/base/debug/trace_event_win_unittest.cc
@@ -106,7 +106,7 @@ class TraceEventTest: public testing::Test {
TraceLog* tracelog = NULL;
if (!is_xp) {
TraceLog::Resurrect();
- tracelog = TraceLog::Get();
+ tracelog = TraceLog::GetInstance();
ASSERT_TRUE(tracelog != NULL);
ASSERT_FALSE(tracelog->IsTracing());
}
@@ -142,7 +142,7 @@ class TraceEventTest: public testing::Test {
if (is_xp) {
TraceLog::Resurrect();
- tracelog = TraceLog::Get();
+ tracelog = TraceLog::GetInstance();
}
ASSERT_TRUE(tracelog != NULL);
EXPECT_TRUE(tracelog->IsTracing());
diff --git a/base/file_descriptor_shuffle.h b/base/file_descriptor_shuffle.h
index a5c08e4..e193035 100644
--- a/base/file_descriptor_shuffle.h
+++ b/base/file_descriptor_shuffle.h
@@ -46,9 +46,9 @@ class InjectionDelegate {
// An implementation of the InjectionDelegate interface using the file
// descriptor table of the current process as the domain.
class FileDescriptorTableInjection : public InjectionDelegate {
- bool Duplicate(int* result, int fd);
- bool Move(int src, int dest);
- void Close(int fd);
+ virtual bool Duplicate(int* result, int fd);
+ virtual bool Move(int src, int dest);
+ virtual void Close(int fd);
};
// A single arc of the directed graph which describes an injective multimapping.
diff --git a/base/file_util.cc b/base/file_util.cc
index 254e649..2b5dc84 100644
--- a/base/file_util.cc
+++ b/base/file_util.cc
@@ -361,14 +361,6 @@ bool MemoryMappedFile::IsValid() {
// Deprecated functions ----------------------------------------------------
#if defined(OS_WIN)
-bool AbsolutePath(std::wstring* path_str) {
- FilePath path(FilePath::FromWStringHack(*path_str));
- if (!AbsolutePath(&path))
- return false;
- *path_str = path.ToWStringHack();
- return true;
-}
-
void AppendToPath(std::wstring* path, const std::wstring& new_ending) {
if (!path) {
NOTREACHED();
diff --git a/base/file_util_deprecated.h b/base/file_util_deprecated.h
index 45e60b7..9bafb31 100644
--- a/base/file_util_deprecated.h
+++ b/base/file_util_deprecated.h
@@ -49,8 +49,6 @@ void AppendToPath(std::wstring* path, const std::wstring& new_ending);
FilePath::StringType GetFileExtensionFromPath(const FilePath& path);
std::wstring GetFileExtensionFromPath(const std::wstring& path);
-bool AbsolutePath(std::wstring* path);
-
// Use version that takes a FilePath.
bool Delete(const std::wstring& path, bool recursive);
bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path,
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
index 56b1ce0..ac6dabb 100644
--- a/base/file_util_posix.cc
+++ b/base/file_util_posix.cc
@@ -388,11 +388,12 @@ bool ReadSymbolicLink(const FilePath& symlink_path,
char buf[PATH_MAX];
ssize_t count = ::readlink(symlink_path.value().c_str(), buf, arraysize(buf));
- if (count <= 0)
+ if (count <= 0) {
+ target_path->clear();
return false;
+ }
*target_path = FilePath(FilePath::StringType(buf, count));
-
return true;
}
diff --git a/base/file_util_win.cc b/base/file_util_win.cc
index 4645acc..3ca52ae 100644
--- a/base/file_util_win.cc
+++ b/base/file_util_win.cc
@@ -163,6 +163,14 @@ bool Delete(const FilePath& path, bool recursive) {
if (!recursive)
file_operation.fFlags |= FOF_NORECURSION | FOF_FILESONLY;
int err = SHFileOperation(&file_operation);
+
+ // Since we're passing flags to the operation telling it to be silent,
+ // it's possible for the operation to be aborted/cancelled without err
+ // being set (although MSDN doesn't give any scenarios for how this can
+ // happen). See MSDN for SHFileOperation and SHFILEOPTSTRUCT.
+ if (file_operation.fAnyOperationsAborted)
+ return false;
+
// Some versions of Windows return ERROR_FILE_NOT_FOUND (0x2) when deleting
// an empty directory and some return 0x402 when they should be returning
// ERROR_FILE_NOT_FOUND. MSDN says Vista and up won't return 0x402.
diff --git a/base/file_version_info.h b/base/file_version_info.h
index 19407d2..481e88d 100644
--- a/base/file_version_info.h
+++ b/base/file_version_info.h
@@ -6,15 +6,23 @@
#define BASE_FILE_VERSION_INFO_H__
#pragma once
+#include "build/build_config.h"
+
#include <string>
-#include "build/build_config.h"
+#include "base/string16.h"
class FilePath;
-// Provides an interface for accessing the version information for a file.
-// This is the information you access when you select a file in the Windows
-// explorer, right-click select Properties, then click the Version tab.
+// Provides an interface for accessing the version information for a file. This
+// is the information you access when you select a file in the Windows Explorer,
+// right-click select Properties, then click the Version tab, and on the Mac
+// when you select a file in the Finder and do a Get Info.
+//
+// This list of properties is straight out of Win32's VerQueryValue
+// <http://msdn.microsoft.com/en-us/library/ms647464.aspx> and the Mac
+// version returns values from the Info.plist as appropriate. TODO(avi): make
+// this a less-obvious Windows-ism.
class FileVersionInfo {
public:
@@ -24,10 +32,7 @@ class FileVersionInfo {
// goes wrong (typically the file does not exit or cannot be opened). The
// returned object should be deleted when you are done with it.
static FileVersionInfo* CreateFileVersionInfo(const FilePath& file_path);
- // This version, taking a wstring, is deprecated and only kept around
- // until we can fix all callers.
- static FileVersionInfo* CreateFileVersionInfo(const std::wstring& file_path);
-#endif
+#endif // OS_WIN || OS_MACOSX
// Creates a FileVersionInfo for the current module. Returns NULL in case
// of error. The returned object should be deleted when you are done with it.
@@ -35,21 +40,21 @@ class FileVersionInfo {
// Accessors to the different version properties.
// Returns an empty string if the property is not found.
- virtual std::wstring company_name() = 0;
- virtual std::wstring company_short_name() = 0;
- virtual std::wstring product_name() = 0;
- virtual std::wstring product_short_name() = 0;
- virtual std::wstring internal_name() = 0;
- virtual std::wstring product_version() = 0;
- virtual std::wstring private_build() = 0;
- virtual std::wstring special_build() = 0;
- virtual std::wstring comments() = 0;
- virtual std::wstring original_filename() = 0;
- virtual std::wstring file_description() = 0;
- virtual std::wstring file_version() = 0;
- virtual std::wstring legal_copyright() = 0;
- virtual std::wstring legal_trademarks() = 0;
- virtual std::wstring last_change() = 0;
+ virtual string16 company_name() = 0;
+ virtual string16 company_short_name() = 0;
+ virtual string16 product_name() = 0;
+ virtual string16 product_short_name() = 0;
+ virtual string16 internal_name() = 0;
+ virtual string16 product_version() = 0;
+ virtual string16 private_build() = 0;
+ virtual string16 special_build() = 0;
+ virtual string16 comments() = 0;
+ virtual string16 original_filename() = 0;
+ virtual string16 file_description() = 0;
+ virtual string16 file_version() = 0;
+ virtual string16 legal_copyright() = 0;
+ virtual string16 legal_trademarks() = 0;
+ virtual string16 last_change() = 0;
virtual bool is_official_build() = 0;
};
diff --git a/base/file_version_info_mac.h b/base/file_version_info_mac.h
index d66c4e6..879edb3 100644
--- a/base/file_version_info_mac.h
+++ b/base/file_version_info_mac.h
@@ -8,9 +8,8 @@
#include <string>
-#include "base/basictypes.h"
#include "base/file_version_info.h"
-#include "base/scoped_ptr.h"
+#include "base/scoped_nsobject.h"
#ifdef __OBJC__
@class NSBundle;
@@ -18,43 +17,37 @@
class NSBundle;
#endif
-// Provides a way to access the version information for a file.
-// This is the information you access when you select a file in the Windows
-// explorer, right-click select Properties, then click the Version tab.
-
class FileVersionInfoMac : public FileVersionInfo {
public:
explicit FileVersionInfoMac(NSBundle *bundle);
- ~FileVersionInfoMac();
// Accessors to the different version properties.
// Returns an empty string if the property is not found.
- virtual std::wstring company_name();
- virtual std::wstring company_short_name();
- virtual std::wstring product_name();
- virtual std::wstring product_short_name();
- virtual std::wstring internal_name();
- virtual std::wstring product_version();
- virtual std::wstring private_build();
- virtual std::wstring special_build();
- virtual std::wstring comments();
- virtual std::wstring original_filename();
- virtual std::wstring file_description();
- virtual std::wstring file_version();
- virtual std::wstring legal_copyright();
- virtual std::wstring legal_trademarks();
- virtual std::wstring last_change();
+ virtual string16 company_name();
+ virtual string16 company_short_name();
+ virtual string16 product_name();
+ virtual string16 product_short_name();
+ virtual string16 internal_name();
+ virtual string16 product_version();
+ virtual string16 private_build();
+ virtual string16 special_build();
+ virtual string16 comments();
+ virtual string16 original_filename();
+ virtual string16 file_description();
+ virtual string16 file_version();
+ virtual string16 legal_copyright();
+ virtual string16 legal_trademarks();
+ virtual string16 last_change();
virtual bool is_official_build();
private:
- // Lets you access other properties not covered above.
- bool GetValue(const wchar_t* name, std::wstring* value);
- // Similar to GetValue but returns a wstring (empty string if the property
- // does not exist).
- std::wstring GetStringValue(const wchar_t* name);
- NSBundle *bundle_;
+ // Returns a string16 value for a property name.
+ // Returns the empty string if the property does not exist.
+ string16 GetString16Value(CFStringRef name);
+
+ scoped_nsobject<NSBundle> bundle_;
DISALLOW_COPY_AND_ASSIGN(FileVersionInfoMac);
};
diff --git a/base/file_version_info_mac.mm b/base/file_version_info_mac.mm
index 57be79a..fa97df8 100644
--- a/base/file_version_info_mac.mm
+++ b/base/file_version_info_mac.mm
@@ -4,103 +4,87 @@
#include "base/file_version_info_mac.h"
-#import <Cocoa/Cocoa.h>
+#import <Foundation/Foundation.h>
-#include "base/basictypes.h"
#include "base/file_path.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
+#include "base/logging.h"
+#include "base/sys_string_conversions.h"
+#include "base/mac_util.h"
FileVersionInfoMac::FileVersionInfoMac(NSBundle *bundle) : bundle_(bundle) {
- [bundle_ retain];
-}
-
-FileVersionInfoMac::~FileVersionInfoMac() {
- [bundle_ release];
}
// static
FileVersionInfo* FileVersionInfo::CreateFileVersionInfoForCurrentModule() {
- // TODO(erikkay): this should really use bundleForClass, but we don't have
- // a class to hang onto yet.
- NSBundle* bundle = [NSBundle mainBundle];
- return new FileVersionInfoMac(bundle);
-}
-
-// static
-FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
- const std::wstring& file_path) {
- NSString* path = [NSString stringWithCString:
- reinterpret_cast<const char*>(file_path.c_str())
- encoding:NSUTF32StringEncoding];
- return new FileVersionInfoMac([NSBundle bundleWithPath:path]);
+ return CreateFileVersionInfo(mac_util::MainAppBundlePath());
}
// static
FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
const FilePath& file_path) {
- NSString* path = [NSString stringWithUTF8String:file_path.value().c_str()];
- return new FileVersionInfoMac([NSBundle bundleWithPath:path]);
+ NSString* path = base::SysUTF8ToNSString(file_path.value());
+ NSBundle* bundle = [NSBundle bundleWithPath:path];
+ return new FileVersionInfoMac(bundle);
}
-std::wstring FileVersionInfoMac::company_name() {
- return std::wstring();
+string16 FileVersionInfoMac::company_name() {
+ return string16();
}
-std::wstring FileVersionInfoMac::company_short_name() {
- return std::wstring();
+string16 FileVersionInfoMac::company_short_name() {
+ return string16();
}
-std::wstring FileVersionInfoMac::internal_name() {
- return std::wstring();
+string16 FileVersionInfoMac::internal_name() {
+ return string16();
}
-std::wstring FileVersionInfoMac::product_name() {
- return GetStringValue(L"CFBundleName");
+string16 FileVersionInfoMac::product_name() {
+ return GetString16Value(kCFBundleNameKey);
}
-std::wstring FileVersionInfoMac::product_short_name() {
- return GetStringValue(L"CFBundleName");
+string16 FileVersionInfoMac::product_short_name() {
+ return GetString16Value(kCFBundleNameKey);
}
-std::wstring FileVersionInfoMac::comments() {
- return std::wstring();
+string16 FileVersionInfoMac::comments() {
+ return string16();
}
-std::wstring FileVersionInfoMac::legal_copyright() {
- return GetStringValue(L"CFBundleGetInfoString");
+string16 FileVersionInfoMac::legal_copyright() {
+ return GetString16Value(CFSTR("CFBundleGetInfoString"));
}
-std::wstring FileVersionInfoMac::product_version() {
- return GetStringValue(L"CFBundleShortVersionString");
+string16 FileVersionInfoMac::product_version() {
+ return GetString16Value(CFSTR("CFBundleShortVersionString"));
}
-std::wstring FileVersionInfoMac::file_description() {
- return std::wstring();
+string16 FileVersionInfoMac::file_description() {
+ return string16();
}
-std::wstring FileVersionInfoMac::legal_trademarks() {
- return std::wstring();
+string16 FileVersionInfoMac::legal_trademarks() {
+ return string16();
}
-std::wstring FileVersionInfoMac::private_build() {
- return std::wstring();
+string16 FileVersionInfoMac::private_build() {
+ return string16();
}
-std::wstring FileVersionInfoMac::file_version() {
+string16 FileVersionInfoMac::file_version() {
return product_version();
}
-std::wstring FileVersionInfoMac::original_filename() {
- return GetStringValue(L"CFBundleName");
+string16 FileVersionInfoMac::original_filename() {
+ return GetString16Value(kCFBundleNameKey);
}
-std::wstring FileVersionInfoMac::special_build() {
- return std::wstring();
+string16 FileVersionInfoMac::special_build() {
+ return string16();
}
-std::wstring FileVersionInfoMac::last_change() {
- return GetStringValue(L"SVNRevision");
+string16 FileVersionInfoMac::last_change() {
+ return GetString16Value(CFSTR("SVNRevision"));
}
bool FileVersionInfoMac::is_official_build() {
@@ -111,23 +95,13 @@ bool FileVersionInfoMac::is_official_build() {
#endif
}
-bool FileVersionInfoMac::GetValue(const wchar_t* name,
- std::wstring* value_str) {
+string16 FileVersionInfoMac::GetString16Value(CFStringRef name) {
if (bundle_) {
- NSString* value = [bundle_ objectForInfoDictionaryKey:
- [NSString stringWithUTF8String:WideToUTF8(name).c_str()]];
+ NSString *ns_name = mac_util::CFToNSCast(name);
+ NSString* value = [bundle_ objectForInfoDictionaryKey:ns_name];
if (value) {
- *value_str = reinterpret_cast<const wchar_t*>(
- [value cStringUsingEncoding:NSUTF32StringEncoding]);
- return true;
+ return base::SysNSStringToUTF16(value);
}
}
- return false;
-}
-
-std::wstring FileVersionInfoMac::GetStringValue(const wchar_t* name) {
- std::wstring str;
- if (GetValue(name, &str))
- return str;
- return std::wstring();
+ return string16();
}
diff --git a/base/file_version_info_win.cc b/base/file_version_info_win.cc
index 6c69708..e2bc84b 100644
--- a/base/file_version_info_win.cc
+++ b/base/file_version_info_win.cc
@@ -77,70 +77,63 @@ FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
}
}
-// static
-FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
- const std::wstring& file_path) {
- FilePath file_path_fp = FilePath::FromWStringHack(file_path);
- return CreateFileVersionInfo(file_path_fp);
-}
-
-std::wstring FileVersionInfoWin::company_name() {
+string16 FileVersionInfoWin::company_name() {
return GetStringValue(L"CompanyName");
}
-std::wstring FileVersionInfoWin::company_short_name() {
+string16 FileVersionInfoWin::company_short_name() {
return GetStringValue(L"CompanyShortName");
}
-std::wstring FileVersionInfoWin::internal_name() {
+string16 FileVersionInfoWin::internal_name() {
return GetStringValue(L"InternalName");
}
-std::wstring FileVersionInfoWin::product_name() {
+string16 FileVersionInfoWin::product_name() {
return GetStringValue(L"ProductName");
}
-std::wstring FileVersionInfoWin::product_short_name() {
+string16 FileVersionInfoWin::product_short_name() {
return GetStringValue(L"ProductShortName");
}
-std::wstring FileVersionInfoWin::comments() {
+string16 FileVersionInfoWin::comments() {
return GetStringValue(L"Comments");
}
-std::wstring FileVersionInfoWin::legal_copyright() {
+string16 FileVersionInfoWin::legal_copyright() {
return GetStringValue(L"LegalCopyright");
}
-std::wstring FileVersionInfoWin::product_version() {
+string16 FileVersionInfoWin::product_version() {
return GetStringValue(L"ProductVersion");
}
-std::wstring FileVersionInfoWin::file_description() {
+string16 FileVersionInfoWin::file_description() {
return GetStringValue(L"FileDescription");
}
-std::wstring FileVersionInfoWin::legal_trademarks() {
+string16 FileVersionInfoWin::legal_trademarks() {
return GetStringValue(L"LegalTrademarks");
}
-std::wstring FileVersionInfoWin::private_build() {
+string16 FileVersionInfoWin::private_build() {
return GetStringValue(L"PrivateBuild");
}
-std::wstring FileVersionInfoWin::file_version() {
+string16 FileVersionInfoWin::file_version() {
return GetStringValue(L"FileVersion");
}
-std::wstring FileVersionInfoWin::original_filename() {
+string16 FileVersionInfoWin::original_filename() {
return GetStringValue(L"OriginalFilename");
}
-std::wstring FileVersionInfoWin::special_build() {
+string16 FileVersionInfoWin::special_build() {
return GetStringValue(L"SpecialBuild");
}
-std::wstring FileVersionInfoWin::last_change() {
+string16 FileVersionInfoWin::last_change() {
return GetStringValue(L"LastChange");
}
diff --git a/base/file_version_info_win.h b/base/file_version_info_win.h
index 3d60d69..4a49314 100644
--- a/base/file_version_info_win.h
+++ b/base/file_version_info_win.h
@@ -15,10 +15,6 @@
struct tagVS_FIXEDFILEINFO;
typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO;
-// Provides a way to access the version information for a file.
-// This is the information you access when you select a file in the Windows
-// explorer, right-click select Properties, then click the Version tab.
-
class FileVersionInfoWin : public FileVersionInfo {
public:
FileVersionInfoWin(void* data, int language, int code_page);
@@ -26,21 +22,21 @@ class FileVersionInfoWin : public FileVersionInfo {
// Accessors to the different version properties.
// Returns an empty string if the property is not found.
- virtual std::wstring company_name();
- virtual std::wstring company_short_name();
- virtual std::wstring product_name();
- virtual std::wstring product_short_name();
- virtual std::wstring internal_name();
- virtual std::wstring product_version();
- virtual std::wstring private_build();
- virtual std::wstring special_build();
- virtual std::wstring comments();
- virtual std::wstring original_filename();
- virtual std::wstring file_description();
- virtual std::wstring file_version();
- virtual std::wstring legal_copyright();
- virtual std::wstring legal_trademarks();
- virtual std::wstring last_change();
+ virtual string16 company_name();
+ virtual string16 company_short_name();
+ virtual string16 product_name();
+ virtual string16 product_short_name();
+ virtual string16 internal_name();
+ virtual string16 product_version();
+ virtual string16 private_build();
+ virtual string16 special_build();
+ virtual string16 comments();
+ virtual string16 original_filename();
+ virtual string16 file_description();
+ virtual string16 file_version();
+ virtual string16 legal_copyright();
+ virtual string16 legal_trademarks();
+ virtual string16 last_change();
virtual bool is_official_build();
// Lets you access other properties not covered above.
diff --git a/base/global_descriptors_posix.cc b/base/global_descriptors_posix.cc
index 8c853a0..2fe953c 100644
--- a/base/global_descriptors_posix.cc
+++ b/base/global_descriptors_posix.cc
@@ -15,6 +15,14 @@ GlobalDescriptors::GlobalDescriptors() {}
GlobalDescriptors::~GlobalDescriptors() {}
+// static
+GlobalDescriptors* GlobalDescriptors::GetInstance() {
+ typedef Singleton<base::GlobalDescriptors,
+ LeakySingletonTraits<base::GlobalDescriptors> >
+ GlobalDescriptorsSingleton;
+ return GlobalDescriptorsSingleton::get();
+}
+
int GlobalDescriptors::MaybeGet(Key key) const {
for (Mapping::const_iterator
i = descriptors_.begin(); i != descriptors_.end(); ++i) {
diff --git a/base/global_descriptors_posix.h b/base/global_descriptors_posix.h
index 8ea743e..ab2b86b 100644
--- a/base/global_descriptors_posix.h
+++ b/base/global_descriptors_posix.h
@@ -41,6 +41,9 @@ class GlobalDescriptors {
// the following constant to the key value:
static const int kBaseDescriptor = 3; // 0, 1, 2 are already taken.
+ // Return the singleton instance of GlobalDescriptors.
+ static GlobalDescriptors* GetInstance();
+
// Get a descriptor given a key. It is a fatal error if the key is not known.
int Get(Key key) const;
// Get a descriptor give a key. Returns -1 on error.
diff --git a/base/hash_tables.h b/base/hash_tables.h
index 5fbe466..d11e19f 100644
--- a/base/hash_tables.h
+++ b/base/hash_tables.h
@@ -58,10 +58,14 @@ using __gnu_cxx::hash_set;
namespace __gnu_cxx {
+<<<<<<< HEAD
#ifndef ANDROID
// Already defined for android
// The GNU C++ library provides identiy hash functions for many integral types,
+=======
+// The GNU C++ library provides identity hash functions for many integral types,
+>>>>>>> chromium.org at r10.0.621.0
// 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
// use it for.
diff --git a/base/i18n/break_iterator.cc b/base/i18n/break_iterator.cc
new file mode 100644
index 0000000..e1b5e29
--- /dev/null
+++ b/base/i18n/break_iterator.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2009 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/i18n/break_iterator.h"
+
+#include "base/logging.h"
+#include "unicode/ubrk.h"
+#include "unicode/uchar.h"
+#include "unicode/ustring.h"
+
+namespace base {
+
+const size_t npos = -1;
+
+BreakIterator::BreakIterator(const string16* str, BreakType break_type)
+ : iter_(NULL),
+ string_(str),
+ break_type_(break_type),
+ prev_(npos),
+ pos_(0) {
+}
+
+BreakIterator::~BreakIterator() {
+ if (iter_)
+ ubrk_close(static_cast<UBreakIterator*>(iter_));
+}
+
+bool BreakIterator::Init() {
+ UErrorCode status = U_ZERO_ERROR;
+ UBreakIteratorType break_type;
+ switch (break_type_) {
+ case BREAK_WORD:
+ break_type = UBRK_WORD;
+ break;
+ case BREAK_SPACE:
+ case BREAK_NEWLINE:
+ break_type = UBRK_LINE;
+ break;
+ default:
+ NOTREACHED() << "invalid break_type_";
+ return false;
+ }
+ iter_ = ubrk_open(break_type, NULL,
+ string_->data(), static_cast<int32_t>(string_->size()),
+ &status);
+ if (U_FAILURE(status)) {
+ NOTREACHED() << "ubrk_open failed";
+ return false;
+ }
+ // Move the iterator to the beginning of the string.
+ ubrk_first(static_cast<UBreakIterator*>(iter_));
+ return true;
+}
+
+bool BreakIterator::Advance() {
+ int32_t pos;
+ int32_t status;
+ prev_ = pos_;
+ switch (break_type_) {
+ case BREAK_WORD:
+ case BREAK_SPACE:
+ pos = ubrk_next(static_cast<UBreakIterator*>(iter_));
+ if (pos == UBRK_DONE) {
+ pos_ = npos;
+ return false;
+ }
+ pos_ = static_cast<size_t>(pos);
+ return true;
+ case BREAK_NEWLINE:
+ do {
+ pos = ubrk_next(static_cast<UBreakIterator*>(iter_));
+ if (pos == UBRK_DONE) {
+ break;
+ }
+ pos_ = static_cast<size_t>(pos);
+ status = ubrk_getRuleStatus(static_cast<UBreakIterator*>(iter_));
+ } while (status >= UBRK_LINE_SOFT && status < UBRK_LINE_SOFT_LIMIT);
+ if (pos == UBRK_DONE && prev_ == pos_) {
+ pos_ = npos;
+ return false;
+ }
+ return true;
+ default:
+ NOTREACHED() << "invalid break_type_";
+ return false;
+ }
+}
+
+bool BreakIterator::IsWord() const {
+ return (break_type_ == BREAK_WORD &&
+ ubrk_getRuleStatus(static_cast<UBreakIterator*>(iter_)) !=
+ UBRK_WORD_NONE);
+}
+
+string16 BreakIterator::GetString() const {
+ DCHECK(prev_ != npos && pos_ != npos);
+ return string_->substr(prev_, pos_ - prev_);
+}
+
+} // namespace base
diff --git a/base/i18n/break_iterator.h b/base/i18n/break_iterator.h
new file mode 100644
index 0000000..9de7ac7
--- /dev/null
+++ b/base/i18n/break_iterator.h
@@ -0,0 +1,108 @@
+// 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.
+
+#ifndef BASE_I18N_BREAK_ITERATOR_H_
+#define BASE_I18N_BREAK_ITERATOR_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+
+// The BreakIterator class iterates through the words, word breaks, and
+// line breaks in a UTF-16 string.
+//
+// It provides several modes, BREAK_WORD, BREAK_SPACE, and BREAK_NEWLINE,
+// which modify how characters are aggregated into the returned string.
+//
+// Under BREAK_WORD mode, once a word is encountered any non-word
+// characters are not included in the returned string (e.g. in the
+// UTF-16 equivalent of the string " foo bar! ", the word breaks are at
+// the periods in ". .foo. .bar.!. .").
+//
+// Under BREAK_SPACE mode, once a word is encountered, any non-word
+// characters are included in the returned string, breaking only when a
+// space-equivalent character is encountered (e.g. in the
+// UTF16-equivalent of the string " foo bar! ", the word breaks are at
+// the periods in ". .foo .bar! .").
+//
+// Under BREAK_NEWLINE mode, all characters are included in the returned
+// string, breking only when a newline-equivalent character is encountered
+// (eg. in the UTF-16 equivalent of the string "foo\nbar!\n\n", the line
+// breaks are at the periods in ".foo\n.bar\n.\n.").
+//
+// To extract the words from a string, move a BREAK_WORD BreakIterator
+// through the string and test whether IsWord() is true. E.g.,
+// BreakIterator iter(&str, BreakIterator::BREAK_WORD);
+// if (!iter.Init()) return false;
+// while (iter.Advance()) {
+// if (iter.IsWord()) {
+// // region [iter.prev(),iter.pos()) contains a word.
+// VLOG(1) << "word: " << iter.GetString();
+// }
+// }
+
+namespace base {
+
+class BreakIterator {
+ public:
+ enum BreakType {
+ BREAK_WORD,
+ BREAK_SPACE,
+ BREAK_NEWLINE,
+ };
+
+ // Requires |str| to live as long as the BreakIterator does.
+ BreakIterator(const string16* str, BreakType break_type);
+ ~BreakIterator();
+
+ // Init() must be called before any of the iterators are valid.
+ // Returns false if ICU failed to initialize.
+ bool Init();
+
+ // Return the current break position within the string,
+ // or BreakIterator::npos when done.
+ size_t pos() const { return pos_; }
+
+ // Return the value of pos() returned before Advance() was last called.
+ size_t prev() const { return prev_; }
+
+ // Advance to the next break. Returns false if we've run past the end of
+ // the string. (Note that the very last "break" is after the final
+ // character in the string, and when we advance to that position it's the
+ // last time Advance() returns true.)
+ bool Advance();
+
+ // Under BREAK_WORD mode, returns true if the break we just hit is the
+ // end of a word. (Otherwise, the break iterator just skipped over e.g.
+ // whitespace or punctuation.) Under BREAK_SPACE and BREAK_NEWLINE modes,
+ // this distinction doesn't apply and it always retuns false.
+ bool IsWord() const;
+
+ // Return the string between prev() and pos().
+ // Advance() must have been called successfully at least once
+ // for pos() to have advanced to somewhere useful.
+ string16 GetString() const;
+
+ private:
+ // ICU iterator, avoiding ICU ubrk.h dependence.
+ // This is actually an ICU UBreakiterator* type, which turns out to be
+ // a typedef for a void* in the ICU headers. Using void* directly prevents
+ // callers from needing access to the ICU public headers directory.
+ void* iter_;
+
+ // The string we're iterating over.
+ const string16* string_;
+
+ // The breaking style (word/space/newline).
+ BreakType break_type_;
+
+ // Previous and current iterator positions.
+ size_t prev_, pos_;
+
+ DISALLOW_COPY_AND_ASSIGN(BreakIterator);
+};
+
+} // namespace base
+
+#endif // BASE_I18N_BREAK_ITERATOR_H__
diff --git a/base/i18n/break_iterator_unittest.cc b/base/i18n/break_iterator_unittest.cc
new file mode 100644
index 0000000..bf4fdc1
--- /dev/null
+++ b/base/i18n/break_iterator_unittest.cc
@@ -0,0 +1,308 @@
+// 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/i18n/break_iterator.h"
+
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(BreakIteratorTest, BreakWordEmpty) {
+ string16 empty;
+ base::BreakIterator iter(&empty, base::BreakIterator::BREAK_WORD);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakWord) {
+ string16 space(UTF8ToUTF16(" "));
+ string16 str(UTF8ToUTF16(" foo bar! \npouet boom"));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_WORD);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(space, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("foo"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(space, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("bar"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("!"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(space, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("\n"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("pouet"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(space, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("boom"), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakWide16) {
+ // Two greek words separated by space.
+ const string16 str(WideToUTF16(
+ L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
+ L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2"));
+ const string16 word1(str.substr(0, 10));
+ const string16 word2(str.substr(11, 5));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_WORD);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(word1, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(word2, iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakWide32) {
+ // U+1D49C MATHEMATICAL SCRIPT CAPITAL A
+ const char* very_wide_char = "\xF0\x9D\x92\x9C";
+ const string16 str(
+ UTF8ToUTF16(StringPrintf("%s a", very_wide_char)));
+ const string16 very_wide_word(str.substr(0, 2));
+
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_WORD);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(very_wide_word, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_TRUE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("a"), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakSpaceEmpty) {
+ string16 empty;
+ base::BreakIterator iter(&empty, base::BreakIterator::BREAK_SPACE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakSpace) {
+ string16 str(UTF8ToUTF16(" foo bar! \npouet boom"));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_SPACE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("foo "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("bar! \n"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("pouet "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("boom"), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakSpaceSP) {
+ string16 str(UTF8ToUTF16(" foo bar! \npouet boom "));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_SPACE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("foo "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("bar! \n"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("pouet "), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("boom "), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakSpacekWide16) {
+ // Two Greek words.
+ const string16 str(WideToUTF16(
+ L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
+ L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2"));
+ const string16 word1(str.substr(0, 11));
+ const string16 word2(str.substr(11, 5));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_SPACE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(word1, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(word2, iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakSpaceWide32) {
+ // U+1D49C MATHEMATICAL SCRIPT CAPITAL A
+ const char* very_wide_char = "\xF0\x9D\x92\x9C";
+ const string16 str(
+ UTF8ToUTF16(StringPrintf("%s a", very_wide_char)));
+ const string16 very_wide_word(str.substr(0, 3));
+
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_SPACE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(very_wide_word, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("a"), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakLineEmpty) {
+ string16 empty;
+ base::BreakIterator iter(&empty, base::BreakIterator::BREAK_NEWLINE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakLine) {
+ string16 nl(UTF8ToUTF16("\n"));
+ string16 str(UTF8ToUTF16("\nfoo bar!\n\npouet boom"));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_NEWLINE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(nl, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("foo bar!\n"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(nl, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("pouet boom"), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakLineNL) {
+ string16 nl(UTF8ToUTF16("\n"));
+ string16 str(UTF8ToUTF16("\nfoo bar!\n\npouet boom\n"));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_NEWLINE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(nl, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("foo bar!\n"), iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(nl, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("pouet boom\n"), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakLineWide16) {
+ // Two Greek words separated by newline.
+ const string16 str(WideToUTF16(
+ L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
+ L"\x03bf\x03c2\x000a\x0399\x03c3\x03c4\x03cc\x03c2"));
+ const string16 line1(str.substr(0, 11));
+ const string16 line2(str.substr(11, 5));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_NEWLINE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(line1, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(line2, iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
+
+TEST(BreakIteratorTest, BreakLineWide32) {
+ // U+1D49C MATHEMATICAL SCRIPT CAPITAL A
+ const char* very_wide_char = "\xF0\x9D\x92\x9C";
+ const string16 str(
+ UTF8ToUTF16(StringPrintf("%s\na", very_wide_char)));
+ const string16 very_wide_line(str.substr(0, 3));
+ base::BreakIterator iter(&str, base::BreakIterator::BREAK_NEWLINE);
+ ASSERT_TRUE(iter.Init());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(very_wide_line, iter.GetString());
+ EXPECT_TRUE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_EQ(UTF8ToUTF16("a"), iter.GetString());
+ EXPECT_FALSE(iter.Advance());
+ EXPECT_FALSE(iter.IsWord());
+ EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
+ EXPECT_FALSE(iter.IsWord());
+}
diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc
index 0e9c2cd..34eefac 100644
--- a/base/i18n/file_util_icu.cc
+++ b/base/i18n/file_util_icu.cc
@@ -21,6 +21,10 @@ namespace {
class IllegalCharacters {
public:
+ static IllegalCharacters* GetInstance() {
+ return Singleton<IllegalCharacters>::get();
+ }
+
bool contains(UChar32 ucs4) {
return !!set->contains(ucs4);
}
@@ -76,19 +80,8 @@ IllegalCharacters::IllegalCharacters() {
class LocaleAwareComparator {
public:
- LocaleAwareComparator() {
- UErrorCode error_code = U_ZERO_ERROR;
- // Use the default collator. The default locale should have been properly
- // set by the time this constructor is called.
- collator_.reset(icu::Collator::createInstance(error_code));
- DCHECK(U_SUCCESS(error_code));
- // Make it case-sensitive.
- collator_->setStrength(icu::Collator::TERTIARY);
- // Note: We do not set UCOL_NORMALIZATION_MODE attribute. In other words, we
- // do not pay performance penalty to guarantee sort order correctness for
- // non-FCD (http://unicode.org/notes/tn5/#FCD) file names. This should be a
- // reasonable tradeoff because such file names should be rare and the sort
- // order doesn't change much anyway.
+ static LocaleAwareComparator* GetInstance() {
+ return Singleton<LocaleAwareComparator>::get();
}
// Note: A similar function is available in l10n_util.
@@ -111,6 +104,21 @@ class LocaleAwareComparator {
}
private:
+ LocaleAwareComparator() {
+ UErrorCode error_code = U_ZERO_ERROR;
+ // Use the default collator. The default locale should have been properly
+ // set by the time this constructor is called.
+ collator_.reset(icu::Collator::createInstance(error_code));
+ DCHECK(U_SUCCESS(error_code));
+ // Make it case-sensitive.
+ collator_->setStrength(icu::Collator::TERTIARY);
+ // Note: We do not set UCOL_NORMALIZATION_MODE attribute. In other words, we
+ // do not pay performance penalty to guarantee sort order correctness for
+ // non-FCD (http://unicode.org/notes/tn5/#FCD) file names. This should be a
+ // reasonable tradeoff because such file names should be rare and the sort
+ // order doesn't change much anyway.
+ }
+
scoped_ptr<icu::Collator> collator_;
Lock lock_;
friend struct DefaultSingletonTraits<LocaleAwareComparator>;
@@ -123,19 +131,19 @@ class LocaleAwareComparator {
namespace file_util {
bool IsFilenameLegal(const string16& file_name) {
- return Singleton<IllegalCharacters>()->containsNone(file_name);
+ return IllegalCharacters::GetInstance()->containsNone(file_name);
}
void ReplaceIllegalCharactersInPath(FilePath::StringType* file_name,
char replace_char) {
DCHECK(file_name);
- DCHECK(!(Singleton<IllegalCharacters>()->contains(replace_char)));
+ DCHECK(!(IllegalCharacters::GetInstance()->contains(replace_char)));
// Remove leading and trailing whitespace.
TrimWhitespace(*file_name, TRIM_ALL, file_name);
- IllegalCharacters* illegal = Singleton<IllegalCharacters>::get();
+ IllegalCharacters* illegal = IllegalCharacters::GetInstance();
int cursor = 0; // The ICU macros expect an int.
while (cursor < static_cast<int>(file_name->size())) {
int char_begin = cursor;
@@ -171,8 +179,8 @@ void ReplaceIllegalCharactersInPath(FilePath::StringType* file_name,
bool LocaleAwareCompareFilenames(const FilePath& a, const FilePath& b) {
#if defined(OS_WIN)
- return Singleton<LocaleAwareComparator>()->Compare(a.value().c_str(),
- b.value().c_str()) < 0;
+ return LocaleAwareComparator::GetInstance()->Compare(a.value().c_str(),
+ b.value().c_str()) < 0;
#elif defined(OS_POSIX)
// On linux, the file system encoding is not defined. We assume
@@ -181,7 +189,7 @@ bool LocaleAwareCompareFilenames(const FilePath& a, const FilePath& b) {
// ICU's collator can take strings in OS native encoding. But we convert the
// strings to UTF-16 ourselves to ensure conversion consistency.
// TODO(yuzo): Perhaps we should define SysNativeMBToUTF16?
- return Singleton<LocaleAwareComparator>()->Compare(
+ return LocaleAwareComparator::GetInstance()->Compare(
WideToUTF16(base::SysNativeMBToWide(a.value().c_str())),
WideToUTF16(base::SysNativeMBToWide(b.value().c_str()))) < 0;
#else
diff --git a/base/i18n/number_formatting.cc b/base/i18n/number_formatting.cc
index 7a69294..df6af14 100644
--- a/base/i18n/number_formatting.cc
+++ b/base/i18n/number_formatting.cc
@@ -6,7 +6,8 @@
#include "base/format_macros.h"
#include "base/logging.h"
-#include "base/singleton.h"
+#include "base/lazy_instance.h"
+#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "unicode/numfmt.h"
@@ -16,25 +17,26 @@ namespace base {
namespace {
-struct NumberFormatSingletonTraits
- : public DefaultSingletonTraits<icu::NumberFormat> {
- static icu::NumberFormat* New() {
+struct NumberFormatWrapper {
+ NumberFormatWrapper() {
+ // There's no ICU call to destroy a NumberFormat object other than
+ // operator delete, so use the default Delete, which calls operator delete.
+ // This can cause problems if a different allocator is used by this file
+ // than by ICU.
UErrorCode status = U_ZERO_ERROR;
- icu::NumberFormat* formatter = icu::NumberFormat::createInstance(status);
+ number_format.reset(icu::NumberFormat::createInstance(status));
DCHECK(U_SUCCESS(status));
- return formatter;
}
- // There's no ICU call to destroy a NumberFormat object other than
- // operator delete, so use the default Delete, which calls operator delete.
- // This can cause problems if a different allocator is used by this file than
- // by ICU.
+
+ scoped_ptr<icu::NumberFormat> number_format;
};
} // namespace
+static LazyInstance<NumberFormatWrapper> g_number_format(LINKER_INITIALIZED);
+
string16 FormatNumber(int64 number) {
- icu::NumberFormat* number_format =
- Singleton<icu::NumberFormat, NumberFormatSingletonTraits>::get();
+ icu::NumberFormat* number_format = g_number_format.Get().number_format.get();
if (!number_format) {
// As a fallback, just return the raw number in a string.
diff --git a/base/i18n/rtl.cc b/base/i18n/rtl.cc
index 6a5d293..12b376d 100644
--- a/base/i18n/rtl.cc
+++ b/base/i18n/rtl.cc
@@ -163,6 +163,7 @@ TextDirection GetFirstStrongCharacterDirection(const std::wstring& text) {
}
#endif
+#if defined(OS_WIN)
bool AdjustStringForLocaleDirection(string16* text) {
if (!IsRTL() || text->empty())
return false;
@@ -177,6 +178,57 @@ bool AdjustStringForLocaleDirection(string16* text) {
return true;
}
+#else
+bool AdjustStringForLocaleDirection(string16* text) {
+ // On OS X & GTK the directionality of a label is determined by the first
+ // strongly directional character.
+ // However, we want to make sure that in an LTR-language-UI all strings are
+ // left aligned and vice versa.
+ // A problem can arise if we display a string which starts with user input.
+ // User input may be of the opposite directionality to the UI. So the whole
+ // string will be displayed in the opposite directionality, e.g. if we want to
+ // display in an LTR UI [such as US English]:
+ //
+ // EMAN_NOISNETXE is now installed.
+ //
+ // Since EXTENSION_NAME begins with a strong RTL char, the label's
+ // directionality will be set to RTL and the string will be displayed visually
+ // as:
+ //
+ // .is now installed EMAN_NOISNETXE
+ //
+ // In order to solve this issue, we prepend an LRM to the string. An LRM is a
+ // strongly directional LTR char.
+ // We also append an LRM at the end, which ensures that we're in an LTR
+ // context.
+
+ // Unlike Windows, Linux and OS X can correctly display RTL glyphs out of the
+ // box so there is no issue with displaying zero-width bidi control characters
+ // on any system. Thus no need for the !IsRTL() check here.
+ if (text->empty())
+ return false;
+
+ bool ui_direction_is_rtl = IsRTL();
+
+ bool has_rtl_chars = StringContainsStrongRTLChars(*text);
+ if (!ui_direction_is_rtl && has_rtl_chars) {
+ WrapStringWithRTLFormatting(text);
+ text->insert(0, 1, kLeftToRightMark);
+ text->push_back(kLeftToRightMark);
+ } else if (ui_direction_is_rtl && has_rtl_chars) {
+ WrapStringWithRTLFormatting(text);
+ text->insert(0, 1, kRightToLeftMark);
+ text->push_back(kRightToLeftMark);
+ } else if (ui_direction_is_rtl) {
+ WrapStringWithLTRFormatting(text);
+ text->insert(0, 1, kRightToLeftMark);
+ text->push_back(kRightToLeftMark);
+ }
+
+ return true;
+}
+
+#endif // !OS_WIN
#if defined(WCHAR_T_IS_UTF32)
bool AdjustStringForLocaleDirection(std::wstring* text) {
diff --git a/base/i18n/rtl.h b/base/i18n/rtl.h
index 82ac576..a75ed4f 100644
--- a/base/i18n/rtl.h
+++ b/base/i18n/rtl.h
@@ -84,6 +84,7 @@ TextDirection GetFirstStrongCharacterDirection(const std::wstring& text);
// string is always treated as a right-to-left string. This is done by
// inserting certain Unicode formatting marks into the returned string.
//
+// ** Notes about the Windows version of this function:
// TODO(idana) bug 6806: this function adjusts the string in question only
// if the current locale is right-to-left. The function does not take care of
// the opposite case (an RTL string displayed in an LTR context) since
diff --git a/base/i18n/time_formatting.cc b/base/i18n/time_formatting.cc
index 406145d..3fa984a 100644
--- a/base/i18n/time_formatting.cc
+++ b/base/i18n/time_formatting.cc
@@ -14,24 +14,21 @@ using base::Time;
namespace {
-std::wstring TimeFormat(const icu::DateFormat* formatter,
- const Time& time) {
+string16 TimeFormat(const icu::DateFormat* formatter,
+ const Time& time) {
DCHECK(formatter);
icu::UnicodeString date_string;
formatter->format(static_cast<UDate>(time.ToDoubleT() * 1000), date_string);
- std::wstring output;
- bool success = UTF16ToWide(date_string.getBuffer(), date_string.length(),
- &output);
- DCHECK(success);
- return output;
+ return string16(date_string.getBuffer(),
+ static_cast<size_t>(date_string.length()));
}
} // namespace
namespace base {
-std::wstring TimeFormatTimeOfDay(const Time& time) {
+string16 TimeFormatTimeOfDay(const Time& time) {
// We can omit the locale parameter because the default should match
// Chrome's application locale.
scoped_ptr<icu::DateFormat> formatter(
@@ -39,31 +36,31 @@ std::wstring TimeFormatTimeOfDay(const Time& time) {
return TimeFormat(formatter.get(), time);
}
-std::wstring TimeFormatShortDate(const Time& time) {
+string16 TimeFormatShortDate(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateInstance(icu::DateFormat::kMedium));
return TimeFormat(formatter.get(), time);
}
-std::wstring TimeFormatShortDateNumeric(const Time& time) {
+string16 TimeFormatShortDateNumeric(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateInstance(icu::DateFormat::kShort));
return TimeFormat(formatter.get(), time);
}
-std::wstring TimeFormatShortDateAndTime(const Time& time) {
+string16 TimeFormatShortDateAndTime(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kShort));
return TimeFormat(formatter.get(), time);
}
-std::wstring TimeFormatFriendlyDateAndTime(const Time& time) {
+string16 TimeFormatFriendlyDateAndTime(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull));
return TimeFormat(formatter.get(), time);
}
-std::wstring TimeFormatFriendlyDate(const Time& time) {
+string16 TimeFormatFriendlyDate(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(icu::DateFormat::createDateInstance(
icu::DateFormat::kFull));
return TimeFormat(formatter.get(), time);
diff --git a/base/i18n/time_formatting.h b/base/i18n/time_formatting.h
index d78ae9b..e70ad3d 100644
--- a/base/i18n/time_formatting.h
+++ b/base/i18n/time_formatting.h
@@ -9,32 +9,32 @@
#define BASE_I18N_TIME_FORMATTING_H_
#pragma once
-#include <string>
+#include "base/string16.h"
namespace base {
class Time;
// Returns the time of day, e.g., "3:07 PM".
-std::wstring TimeFormatTimeOfDay(const Time& time);
+string16 TimeFormatTimeOfDay(const Time& time);
// Returns a shortened date, e.g. "Nov 7, 2007"
-std::wstring TimeFormatShortDate(const Time& time);
+string16 TimeFormatShortDate(const Time& time);
// Returns a numeric date such as 12/13/52.
-std::wstring TimeFormatShortDateNumeric(const Time& time);
+string16 TimeFormatShortDateNumeric(const Time& time);
// Formats a time in a friendly sentence format, e.g.
// "Monday, March 6, 2008 2:44:30 PM".
-std::wstring TimeFormatShortDateAndTime(const Time& time);
+string16 TimeFormatShortDateAndTime(const Time& time);
// Formats a time in a friendly sentence format, e.g.
// "Monday, March 6, 2008 2:44:30 PM".
-std::wstring TimeFormatFriendlyDateAndTime(const Time& time);
+string16 TimeFormatFriendlyDateAndTime(const Time& time);
// Formats a time in a friendly sentence format, e.g.
// "Monday, March 6, 2008".
-std::wstring TimeFormatFriendlyDate(const Time& time);
+string16 TimeFormatFriendlyDate(const Time& time);
} // namespace base
diff --git a/base/i18n/word_iterator.cc b/base/i18n/word_iterator.cc
deleted file mode 100644
index a9fa4af..0000000
--- a/base/i18n/word_iterator.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2009 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/i18n/word_iterator.h"
-
-#include "base/logging.h"
-#include "unicode/ubrk.h"
-#include "unicode/ustring.h"
-
-const size_t npos = -1;
-
-WordIterator::WordIterator(const string16* str, BreakType break_type)
- : iter_(NULL),
- string_(str),
- break_type_(break_type),
- prev_(npos),
- pos_(0) {
-}
-
-WordIterator::~WordIterator() {
- if (iter_)
- ubrk_close(iter_);
-}
-
-bool WordIterator::Init() {
- UErrorCode status = U_ZERO_ERROR;
- UBreakIteratorType break_type;
- switch (break_type_) {
- case BREAK_WORD:
- break_type = UBRK_WORD;
- break;
- case BREAK_LINE:
- break_type = UBRK_LINE;
- break;
- default:
- NOTREACHED();
- break_type = UBRK_LINE;
- }
- iter_ = ubrk_open(break_type, NULL,
- string_->data(), static_cast<int32_t>(string_->size()),
- &status);
- if (U_FAILURE(status)) {
- NOTREACHED() << "ubrk_open failed";
- return false;
- }
- ubrk_first(iter_); // Move the iterator to the beginning of the string.
- return true;
-}
-
-bool WordIterator::Advance() {
- prev_ = pos_;
- const int32_t pos = ubrk_next(iter_);
- if (pos == UBRK_DONE) {
- pos_ = npos;
- return false;
- } else {
- pos_ = static_cast<size_t>(pos);
- return true;
- }
-}
-
-bool WordIterator::IsWord() const {
- return (ubrk_getRuleStatus(iter_) != UBRK_WORD_NONE);
-}
-
-string16 WordIterator::GetWord() const {
- DCHECK(prev_ != npos && pos_ != npos);
- return string_->substr(prev_, pos_ - prev_);
-}
diff --git a/base/i18n/word_iterator.h b/base/i18n/word_iterator.h
deleted file mode 100644
index b097bc2..0000000
--- a/base/i18n/word_iterator.h
+++ /dev/null
@@ -1,89 +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.
-
-#ifndef BASE_I18N_WORD_ITERATOR_H_
-#define BASE_I18N_WORD_ITERATOR_H_
-#pragma once
-
-#include <vector>
-
-#include "unicode/ubrk.h"
-#include "unicode/uchar.h"
-
-#include "base/basictypes.h"
-#include "base/string16.h"
-
-// The WordIterator class iterates through the words and word breaks
-// in a string. (In the string " foo bar! ", the word breaks are at the
-// periods in ". .foo. .bar.!. .".)
-//
-// To extract the words from a string, move a WordIterator through the
-// string and test whether IsWord() is true. E.g.,
-// WordIterator iter(&str, WordIterator::BREAK_WORD);
-// if (!iter.Init()) return false;
-// while (iter.Advance()) {
-// if (iter.IsWord()) {
-// // region [iter.prev(),iter.pos()) contains a word.
-// VLOG(1) << "word: " << iter.GetWord();
-// }
-// }
-
-
-class WordIterator {
- public:
- enum BreakType {
- BREAK_WORD,
- BREAK_LINE
- };
-
- // Requires |str| to live as long as the WordIterator does.
- WordIterator(const string16* str, BreakType break_type);
- ~WordIterator();
-
- // Init() must be called before any of the iterators are valid.
- // Returns false if ICU failed to initialize.
- bool Init();
-
- // Return the current break position within the string,
- // or WordIterator::npos when done.
- size_t pos() const { return pos_; }
- // Return the value of pos() returned before Advance() was last called.
- size_t prev() const { return prev_; }
-
- // Advance to the next break. Returns false if we've run past the end of
- // the string. (Note that the very last "word break" is after the final
- // character in the string, and when we advance to that position it's the
- // last time Advance() returns true.)
- bool Advance();
-
- // Returns true if the break we just hit is the end of a word.
- // (Otherwise, the break iterator just skipped over e.g. whitespace
- // or punctuation.)
- bool IsWord() const;
-
- // Return the word between prev() and pos().
- // Advance() must have been called successfully at least once
- // for pos() to have advanced to somewhere useful.
- string16 GetWord() const;
-
- private:
- // ICU iterator.
- UBreakIterator* iter_;
-#if !defined(WCHAR_T_IS_UTF16)
- std::vector<UChar> chars_;
-#endif
-
- // The string we're iterating over.
- const string16* string_;
-
- // The breaking style (word/line).
- BreakType break_type_;
-
- // Previous and current iterator positions.
- size_t prev_, pos_;
-
- DISALLOW_COPY_AND_ASSIGN(WordIterator);
-};
-
-#endif // BASE_I18N_WORD_ITERATOR_H__
diff --git a/base/i18n/word_iterator_unittest.cc b/base/i18n/word_iterator_unittest.cc
deleted file mode 100644
index 92aff76..0000000
--- a/base/i18n/word_iterator_unittest.cc
+++ /dev/null
@@ -1,117 +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/i18n/word_iterator.h"
-
-#include "base/string_piece.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(WordIteratorTest, BreakWord) {
- string16 space(UTF8ToUTF16(" "));
-
- string16 str(UTF8ToUTF16(" foo bar! \npouet boom"));
- WordIterator iter(&str, WordIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("foo"), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("bar"), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("!"), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("\n"), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("pouet"), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("boom"), iter.GetWord());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(WordIteratorTest, BreakLine) {
- string16 str(UTF8ToUTF16(" foo bar! \npouet boom"));
- WordIterator iter(&str, WordIterator::BREAK_LINE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(" "), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("foo "), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("bar! \n"), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("pouet "), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("boom"), iter.GetWord());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(WordIteratorTest, BreakWide16) {
- // "Παγκόσμιος Ιστός"
- const string16 str(WideToUTF16(
- L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
- L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2"));
- const string16 word1(str.substr(0, 10));
- const string16 word2(str.substr(11, 5));
- WordIterator iter(&str, WordIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(word1, iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(" "), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(word2, iter.GetWord());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(WordIteratorTest, BreakWide32) {
- // U+1D49C MATHEMATICAL SCRIPT CAPITAL A
- const char* very_wide_char = "\xF0\x9D\x92\x9C";
- const string16 str(
- UTF8ToUTF16(StringPrintf("%s a", very_wide_char)));
- const string16 very_wide_word(str.substr(0, 2));
-
- WordIterator iter(&str, WordIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(very_wide_word, iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(" "), iter.GetWord());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("a"), iter.GetWord());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
diff --git a/base/image_util.cc b/base/image_util.cc
deleted file mode 100644
index d17158f..0000000
--- a/base/image_util.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2006-2008 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 <windows.h>
-#include <ImageHlp.h>
-#include <psapi.h>
-
-#include "base/image_util.h"
-#include "base/process_util.h"
-
-// imagehlp.dll appears to ship in all win versions after Win95.
-// nsylvain verified it is present in win2k.
-// Using #pragma comment for dependency, instead of LoadLibrary/GetProcAddress.
-#pragma comment(lib, "imagehlp.lib")
-
-namespace image_util {
-
-// ImageMetrics
-ImageMetrics::ImageMetrics(HANDLE process) : process_(process) {
-}
-
-ImageMetrics::~ImageMetrics() {
-}
-
-bool ImageMetrics::GetDllImageSectionData(const std::string& loaded_dll_name,
- ImageSectionsData* section_sizes) {
- // Get a handle to the loaded DLL
- HMODULE the_dll = GetModuleHandleA(loaded_dll_name.c_str());
- char full_filename[MAX_PATH];
- // Get image path
- if (GetModuleFileNameExA(process_, the_dll, full_filename, MAX_PATH)) {
- return GetImageSectionSizes(full_filename, section_sizes);
- }
- return false;
-}
-
-bool ImageMetrics::GetProcessImageSectionData(ImageSectionsData*
- section_sizes) {
- char exe_path[MAX_PATH];
- // Get image path
- if (GetModuleFileNameExA(process_, NULL, exe_path, MAX_PATH)) {
- return GetImageSectionSizes(exe_path, section_sizes);
- }
- return false;
-}
-
-// private
-bool ImageMetrics::GetImageSectionSizes(char* qualified_path,
- ImageSectionsData* result) {
- LOADED_IMAGE li;
- // TODO (timsteele): There is no unicode version for MapAndLoad, hence
- // why ansi functions are used in this class. Should we try and rewrite
- // this call ourselves to be safe?
- if (MapAndLoad(qualified_path, 0, &li, FALSE, TRUE)) {
- IMAGE_SECTION_HEADER* section_header = li.Sections;
- for (unsigned i = 0; i < li.NumberOfSections; i++, section_header++) {
- std::string name(reinterpret_cast<char*>(section_header->Name));
- ImageSectionData data(name, section_header->Misc.VirtualSize ?
- section_header->Misc.VirtualSize :
- section_header->SizeOfRawData);
- // copy into result
- result->push_back(data);
- }
- } else {
- // map and load failed
- return false;
- }
- UnMapAndLoad(&li);
- return true;
-}
-
-} // namespace image_util
diff --git a/base/image_util.h b/base/image_util.h
deleted file mode 100644
index ccdffc3..0000000
--- a/base/image_util.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-// This file/namespace contains utility functions for gathering
-// information about PE (Portable Executable) headers within
-// images (dll's / exe's )
-
-#ifndef BASE_IMAGE_UTIL_H_
-#define BASE_IMAGE_UTIL_H_
-#pragma once
-
-#include <windows.h>
-#include <vector>
-
-#include "base/basictypes.h"
-
-namespace image_util {
-
-// Contains both the PE section name (.text, .reloc etc) and its size.
-struct ImageSectionData {
- ImageSectionData(const std::string& section_name, size_t section_size)
- : name(section_name),
- size_in_bytes(section_size) {
- }
-
- std::string name;
- size_t size_in_bytes;
-};
-
-typedef std::vector<ImageSectionData> ImageSectionsData;
-
-// Provides image statistics for modules of a specified process, or for the
-// specified process' own executable file. To use, invoke CreateImageMetrics()
-// to get an instance for a specified process, then access the information via
-// methods.
-class ImageMetrics {
- public:
- // Creates an ImageMetrics instance for given process owned by
- // the caller.
- explicit ImageMetrics(HANDLE process);
- ~ImageMetrics();
-
- // Fills a vector of ImageSectionsData containing name/size info
- // for every section found in the specified dll's PE section table.
- // The DLL must be loaded by the process associated with this ImageMetrics
- // instance.
- bool GetDllImageSectionData(const std::string& loaded_dll_name,
- ImageSectionsData* section_sizes);
-
- // Fills a vector if ImageSectionsData containing name/size info
- // for every section found in the executable file of the process
- // associated with this ImageMetrics instance.
- bool GetProcessImageSectionData(ImageSectionsData* section_sizes);
-
- private:
- // Helper for GetDllImageSectionData and GetProcessImageSectionData
- bool GetImageSectionSizes(char* qualified_path, ImageSectionsData* result);
-
- HANDLE process_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageMetrics);
-};
-
-} // namespace image_util
-
-#endif // BASE_IMAGE_UTIL_H_
diff --git a/base/lazy_instance.h b/base/lazy_instance.h
index f8d5987..bdf5ce3 100644
--- a/base/lazy_instance.h
+++ b/base/lazy_instance.h
@@ -127,7 +127,9 @@ class LazyInstance : public LazyInstanceHelper {
NeedsInstance()) {
// Create the instance in the space provided by |buf_|.
instance_ = Traits::New(buf_);
- CompleteInstance(instance_, Traits::Delete);
+ // Traits::Delete will be null for LeakyLazyInstannceTraits
+ void (*dtor)(void*) = Traits::Delete;
+ CompleteInstance(this, (dtor == NULL) ? NULL : OnExit);
}
// This annotation helps race detectors recognize correct lock-less
@@ -140,6 +142,17 @@ class LazyInstance : public LazyInstanceHelper {
}
private:
+ // Adapter function for use with AtExit. This should be called single
+ // threaded, so don't use atomic operations.
+ // Calling OnExit while the instance is in use by other threads is a mistake.
+ static void OnExit(void* lazy_instance) {
+ LazyInstance<Type, Traits>* me =
+ reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance);
+ Traits::Delete(me->instance_);
+ me->instance_ = NULL;
+ base::subtle::Release_Store(&me->state_, STATE_EMPTY);
+ }
+
int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
Type *instance_;
diff --git a/base/linux_util.cc b/base/linux_util.cc
index 62931ce..e1f7275 100644
--- a/base/linux_util.cc
+++ b/base/linux_util.cc
@@ -38,7 +38,7 @@ enum LinuxDistroState {
class LinuxDistroHelper {
public:
// Retrieves the Singleton.
- static LinuxDistroHelper* Get() {
+ static LinuxDistroHelper* GetInstance() {
return Singleton<LinuxDistroHelper>::get();
}
@@ -141,7 +141,7 @@ std::string GetLinuxDistro() {
#if defined(OS_CHROMEOS)
return g_linux_distro;
#elif defined(OS_LINUX)
- LinuxDistroHelper* distro_state_singleton = LinuxDistroHelper::Get();
+ LinuxDistroHelper* distro_state_singleton = LinuxDistroHelper::GetInstance();
LinuxDistroState state = distro_state_singleton->State();
if (STATE_DID_NOT_CHECK == state) {
// We do this check only once per process. If it fails, there's
diff --git a/base/logging.cc b/base/logging.cc
index a202e05..17db628 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -51,14 +51,19 @@ typedef pthread_mutex_t* MutexHandle;
#include "base/debug/stack_trace.h"
#include "base/eintr_wrapper.h"
#include "base/lock_impl.h"
-#if defined(OS_POSIX)
-#include "base/safe_strerror_posix.h"
-#endif
-#include "base/process_util.h"
#include "base/string_piece.h"
#include "base/utf_string_conversions.h"
#ifndef ANDROID
#include "base/vlog.h"
+<<<<<<< HEAD
+=======
+#if defined(OS_POSIX)
+#include "base/safe_strerror_posix.h"
+#endif
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_cftyperef.h"
+#include "base/sys_string_conversions.h"
+>>>>>>> chromium.org at r10.0.621.0
#endif
namespace logging {
@@ -469,6 +474,9 @@ template std::string* MakeCheckOpString<std::string, std::string>(
// Displays a message box to the user with the error message in it.
// Used for fatal messages, where we close the app simultaneously.
+// This is for developers only; we don't use this in circumstances
+// (like release builds) where users could see it, since users don't
+// understand these messages anyway.
void DisplayDebugMessageInDialog(const std::string& str) {
if (str.empty())
return;
@@ -509,19 +517,15 @@ void DisplayDebugMessageInDialog(const std::string& str) {
MessageBoxW(NULL, &cmdline[0], L"Fatal error",
MB_OK | MB_ICONHAND | MB_TOPMOST);
}
-#elif defined(USE_X11) && !defined(OS_CHROMEOS)
- // Shell out to xmessage, which behaves like debug_message.exe, but is
- // way more retro. We could use zenity/kdialog but then we're starting
- // to get into needing to check the desktop env and this dialog should
- // only be coming up in Very Bad situations.
- std::vector<std::string> argv;
- argv.push_back("xmessage");
- argv.push_back(str);
- base::LaunchApp(argv, base::file_handle_mapping_vector(), true /* wait */,
- NULL);
+#elif defined(OS_MACOSX)
+ base::mac::ScopedCFTypeRef<CFStringRef> message(
+ base::SysUTF8ToCFStringRef(str));
+ CFUserNotificationDisplayNotice(0, kCFUserNotificationStopAlertLevel,
+ NULL, NULL, NULL, CFSTR("Fatal Error"),
+ message, NULL);
#else
- // http://code.google.com/p/chromium/issues/detail?id=37026
- NOTIMPLEMENTED();
+ // We intentionally don't implement a dialog on other platforms.
+ // You can just look at stderr.
#endif
}
@@ -602,7 +606,7 @@ void LogMessage::Init(const char* file, int line) {
else
stream_ << "VERBOSE" << -severity_;
- stream_ << ":" << file << "(" << line << ")] ";
+ stream_ << ":" << filename << "(" << line << ")] ";
message_start_ = stream_.tellp();
}
diff --git a/base/logging_win.cc b/base/logging_win.cc
index 42610b5..f780b5e 100644
--- a/base/logging_win.cc
+++ b/base/logging_win.cc
@@ -6,14 +6,6 @@
#include "base/singleton.h"
#include <initguid.h> // NOLINT
-namespace {
-
-typedef StaticMemorySingletonTraits<logging::LogEventProvider>
- LogEventSingletonTraits;
-Singleton<logging::LogEventProvider, LogEventSingletonTraits> log_provider;
-
-} // namespace
-
namespace logging {
using base::win::EtwEventLevel;
@@ -25,6 +17,11 @@ DEFINE_GUID(kLogEventId,
LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) {
}
+LogEventProvider* LogEventProvider::GetInstance() {
+ return Singleton<LogEventProvider,
+ StaticMemorySingletonTraits<LogEventProvider> >::get();
+}
+
bool LogEventProvider::LogMessage(logging::LogSeverity severity,
const char* file, int line, size_t message_start,
const std::string& message) {
@@ -53,7 +50,7 @@ bool LogEventProvider::LogMessage(logging::LogSeverity severity,
// Bail if we're not logging, not at that level,
// or if we're post-atexit handling.
- LogEventProvider* provider = log_provider.get();
+ LogEventProvider* provider = LogEventProvider::GetInstance();
if (provider == NULL || level > provider->enable_level())
return false;
@@ -100,7 +97,7 @@ bool LogEventProvider::LogMessage(logging::LogSeverity severity,
}
void LogEventProvider::Initialize(const GUID& provider_name) {
- LogEventProvider* provider = log_provider.get();
+ LogEventProvider* provider = LogEventProvider::GetInstance();
provider->set_provider_name(provider_name);
provider->Register();
@@ -110,7 +107,7 @@ void LogEventProvider::Initialize(const GUID& provider_name) {
}
void LogEventProvider::Uninitialize() {
- log_provider.get()->Unregister();
+ LogEventProvider::GetInstance()->Unregister();
}
void LogEventProvider::OnEventsEnabled() {
diff --git a/base/logging_win.h b/base/logging_win.h
index 695c7f2..9058c84 100644
--- a/base/logging_win.h
+++ b/base/logging_win.h
@@ -11,6 +11,9 @@
#include "base/win/event_trace_provider.h"
#include "base/logging.h"
+template <typename Type>
+struct StaticMemorySingletonTraits;
+
namespace logging {
// Event ID for the log messages we generate.
@@ -47,7 +50,7 @@ enum LogMessageTypes {
// with Event Tracing for Windows.
class LogEventProvider : public base::win::EtwTraceProvider {
public:
- LogEventProvider();
+ static LogEventProvider* GetInstance();
static bool LogMessage(logging::LogSeverity severity, const char* file,
int line, size_t message_start, const std::string& str);
@@ -61,10 +64,13 @@ class LogEventProvider : public base::win::EtwTraceProvider {
virtual void OnEventsDisabled();
private:
+ LogEventProvider();
+
// The log severity prior to OnEventsEnabled,
// restored in OnEventsDisabled.
logging::LogSeverity old_log_level_;
+ friend struct StaticMemorySingletonTraits<LogEventProvider>;
DISALLOW_COPY_AND_ASSIGN(LogEventProvider);
};
diff --git a/base/cocoa_protocols_mac.h b/base/mac/cocoa_protocols.h
index 9482d51..9482d51 100644
--- a/base/cocoa_protocols_mac.h
+++ b/base/mac/cocoa_protocols.h
diff --git a/base/mac_util.h b/base/mac_util.h
index d31bf82..076865d 100644
--- a/base/mac_util.h
+++ b/base/mac_util.h
@@ -10,16 +10,20 @@
#include <string>
#include <vector>
-class FilePath;
+#include "base/logging.h"
+
+#if defined(__OBJC__)
+#import <Foundation/Foundation.h>
-#ifdef __OBJC__
@class NSBundle;
@class NSWindow;
-#else
+#else // __OBJC__
class NSBundle;
class NSImage;
class NSWindow;
-#endif
+#endif // __OBJC__
+
+class FilePath;
// Adapted from NSPathUtilities.h and NSObjCRuntime.h.
#if __LP64__ || NS_BUILD_32_LIKE_64
@@ -188,6 +192,56 @@ bool WasLaunchedAsHiddenLoginItem();
void NSObjectRetain(void* obj);
void NSObjectRelease(void* obj);
+#if defined(__OBJC__)
+
+// Convert toll-free bridged CFTypes to NSTypes. This does not autorelease
+// |cf_val|. This is useful for the case where there is a CFType in a call that
+// expects an NSType and the compiler is complaining about const casting
+// problems.
+// The call is used like this:
+// NSString *foo = CFToNSCast(CFSTR("Hello"));
+// The macro magic below is to enforce safe casting. It could possibly have
+// been done using template function specialization, but template function
+// specialization doesn't always work intuitively,
+// (http://www.gotw.ca/publications/mill17.htm) so the trusty combination
+// of macros and function overloading is used instead.
+
+#define CF_TO_NS_CAST(TypeCF, TypeNS) \
+inline TypeNS* CFToNSCast(TypeCF cf_val) { \
+ TypeNS* ns_val = \
+ const_cast<TypeNS*>(reinterpret_cast<const TypeNS*>(cf_val)); \
+ DCHECK(!ns_val || [ns_val isKindOfClass:[TypeNS class]]); \
+ return ns_val; \
+}
+
+// List of toll-free bridged types taken from:
+// http://www.cocoadev.com/index.pl?TollFreeBridged
+
+CF_TO_NS_CAST(CFArrayRef, NSArray);
+CF_TO_NS_CAST(CFMutableArrayRef, NSMutableArray);
+CF_TO_NS_CAST(CFAttributedStringRef, NSAttributedString);
+CF_TO_NS_CAST(CFMutableAttributedStringRef, NSMutableAttributedString);
+CF_TO_NS_CAST(CFCalendarRef, NSCalendar);
+CF_TO_NS_CAST(CFCharacterSetRef, NSCharacterSet);
+CF_TO_NS_CAST(CFMutableCharacterSetRef, NSMutableCharacterSet);
+CF_TO_NS_CAST(CFDataRef, NSData);
+CF_TO_NS_CAST(CFMutableDataRef, NSMutableData);
+CF_TO_NS_CAST(CFDateRef, NSDate);
+CF_TO_NS_CAST(CFDictionaryRef, NSDictionary);
+CF_TO_NS_CAST(CFMutableDictionaryRef, NSMutableDictionary);
+CF_TO_NS_CAST(CFNumberRef, NSNumber);
+CF_TO_NS_CAST(CFRunLoopTimerRef, NSTimer);
+CF_TO_NS_CAST(CFSetRef, NSSet);
+CF_TO_NS_CAST(CFMutableSetRef, NSMutableSet);
+CF_TO_NS_CAST(CFStringRef, NSString);
+CF_TO_NS_CAST(CFMutableStringRef, NSMutableString);
+CF_TO_NS_CAST(CFURLRef, NSURL);
+CF_TO_NS_CAST(CFTimeZoneRef, NSTimeZone);
+CF_TO_NS_CAST(CFReadStreamRef, NSInputStream);
+CF_TO_NS_CAST(CFWriteStreamRef, NSOutputStream);
+
+#endif // __OBJC__
+
} // namespace mac_util
#endif // BASE_MAC_UTIL_H_
diff --git a/base/mac_util.mm b/base/mac_util.mm
index 9610d37..598f69b 100644
--- a/base/mac_util.mm
+++ b/base/mac_util.mm
@@ -55,19 +55,17 @@ void SetUIMode() {
bool WasLaunchedAsLoginItem() {
ProcessSerialNumber psn = { 0, kCurrentProcess };
- scoped_nsobject<const NSDictionary> process_info(
- reinterpret_cast<const NSDictionary*>(
- ProcessInformationCopyDictionary(&psn,
- kProcessDictionaryIncludeAllInformationMask)));
+ scoped_nsobject<NSDictionary> process_info(
+ mac_util::CFToNSCast(ProcessInformationCopyDictionary(&psn,
+ kProcessDictionaryIncludeAllInformationMask)));
long long temp = [[process_info objectForKey:@"ParentPSN"] longLongValue];
ProcessSerialNumber parent_psn =
{ (temp >> 32) & 0x00000000FFFFFFFFLL, temp & 0x00000000FFFFFFFFLL };
- scoped_nsobject<const NSDictionary> parent_info(
- reinterpret_cast<const NSDictionary*>(
- ProcessInformationCopyDictionary(&parent_psn,
- kProcessDictionaryIncludeAllInformationMask)));
+ scoped_nsobject<NSDictionary> parent_info(
+ mac_util::CFToNSCast(ProcessInformationCopyDictionary(&parent_psn,
+ kProcessDictionaryIncludeAllInformationMask)));
// Check that creator process code is that of loginwindow.
BOOL result =
@@ -88,9 +86,8 @@ LSSharedFileListItemRef GetLoginItemForApp() {
return NULL;
}
- scoped_nsobject<const NSArray> login_items_array(
- reinterpret_cast<const NSArray*>(
- LSSharedFileListCopySnapshot(login_items, NULL)));
+ scoped_nsobject<NSArray> login_items_array(
+ mac_util::CFToNSCast(LSSharedFileListCopySnapshot(login_items, NULL)));
NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
@@ -563,7 +560,7 @@ void SetProcessName(CFStringRef process_name) {
if (!ls_set_application_information_item_func)
LOG(ERROR) << "Could not find _LSSetApplicationInformationItem";
- const CFStringRef* key_pointer = reinterpret_cast<const CFStringRef*>(
+ CFStringRef* key_pointer = reinterpret_cast<CFStringRef*>(
CFBundleGetDataPointerForName(launch_services_bundle,
CFSTR("_kLSDisplayNameKey")));
ls_display_name_key = key_pointer ? *key_pointer : NULL;
diff --git a/base/mac_util_unittest.mm b/base/mac_util_unittest.mm
index 7999878..63ea9b2 100644
--- a/base/mac_util_unittest.mm
+++ b/base/mac_util_unittest.mm
@@ -7,10 +7,10 @@
#include "base/mac_util.h"
-#import "base/chrome_application_mac.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/mac/scoped_cftyperef.h"
+#include "base/test/mock_chrome_application_mac.h"
#include "base/scoped_nsobject.h"
#include "base/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -54,7 +54,7 @@ TEST_F(MacUtilTest, TestLibraryPath) {
TEST_F(MacUtilTest, TestGrabWindowSnapshot) {
// Launch a test window so we can take a snapshot.
- [CrApplication sharedApplication];
+ [MockCrApp sharedApplication];
NSRect frame = NSMakeRect(0, 0, 400, 400);
scoped_nsobject<NSWindow> window(
[[NSWindow alloc] initWithContentRect:frame
diff --git a/base/message_loop.cc b/base/message_loop.cc
index 11c7198..98c7ceb 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -26,7 +26,6 @@
#include "base/message_pump_glib_x.h"
#endif
-using base::Time;
using base::TimeDelta;
using base::TimeTicks;
@@ -141,9 +140,13 @@ MessageLoop::MessageLoop(Type type)
#define MESSAGE_PUMP_UI new base::MessagePumpDefault()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
#elif defined(TOUCH_UI)
-// TODO(sadrul): enable the new message pump when ready
-#define MESSAGE_PUMP_UI new base::MessagePumpForUI()
+#define MESSAGE_PUMP_UI new base::MessagePumpGlibX()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
+#elif defined(OS_NACL)
+// Currently NaCl doesn't have a UI or an IO MessageLoop.
+// TODO(abarth): Figure out if we need these.
+#define MESSAGE_PUMP_UI NULL
+#define MESSAGE_PUMP_IO NULL
#elif defined(OS_POSIX) // POSIX but not MACOSX.
#define MESSAGE_PUMP_UI new base::MessagePumpForUI()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
@@ -347,9 +350,9 @@ void MessageLoop::PostTask_Helper(
// res timers for any timer which is within 2x of the granularity.
// This is a tradeoff between accuracy and power management.
bool needs_high_res_timers =
- delay_ms < (2 * Time::kMinLowResolutionThresholdMs);
+ delay_ms < (2 * base::Time::kMinLowResolutionThresholdMs);
if (needs_high_res_timers) {
- Time::ActivateHighResolutionTimer(true);
+ base::Time::ActivateHighResolutionTimer(true);
high_resolution_timer_expiration_ = TimeTicks::Now() +
TimeDelta::FromMilliseconds(kHighResolutionTimerModeLeaseTimeMs);
}
@@ -362,7 +365,7 @@ void MessageLoop::PostTask_Helper(
#if defined(OS_WIN)
if (!high_resolution_timer_expiration_.is_null()) {
if (TimeTicks::Now() > high_resolution_timer_expiration_) {
- Time::ActivateHighResolutionTimer(false);
+ base::Time::ActivateHighResolutionTimer(false);
high_resolution_timer_expiration_ = TimeTicks();
}
}
@@ -640,7 +643,7 @@ void MessageLoop::EnableHistogrammer(bool enable) {
void MessageLoop::StartHistogrammer() {
if (enable_histogrammer_ && !message_histogram_.get()
- && base::StatisticsRecorder::WasStarted()) {
+ && base::StatisticsRecorder::IsActive()) {
DCHECK(!thread_name_.empty());
message_histogram_ = base::LinearHistogram::FactoryGet(
"MsgLoop:" + thread_name_,
@@ -665,7 +668,11 @@ void MessageLoopForUI::DidProcessMessage(const MSG& message) {
}
#endif // defined(OS_WIN)
+<<<<<<< HEAD
#if !defined(OS_MACOSX) && !defined(ANDROID)
+=======
+#if !defined(OS_MACOSX) && !defined(OS_NACL)
+>>>>>>> chromium.org at r10.0.621.0
void MessageLoopForUI::AddObserver(Observer* observer) {
pump_ui()->AddObserver(observer);
}
@@ -679,7 +686,7 @@ void MessageLoopForUI::Run(Dispatcher* dispatcher) {
state_->dispatcher = dispatcher;
RunHandler();
}
-#endif // !defined(OS_MACOSX)
+#endif // !defined(OS_MACOSX) && !defined(OS_NACL)
//------------------------------------------------------------------------------
// MessageLoopForIO
@@ -694,7 +701,7 @@ bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
return pump_io()->WaitForIOCompletion(timeout, filter);
}
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) && !defined(OS_NACL)
bool MessageLoopForIO::WatchFileDescriptor(int fd,
bool persistent,
diff --git a/base/message_loop_proxy_impl.h b/base/message_loop_proxy_impl.h
index 87ae70a..44ab2ea 100644
--- a/base/message_loop_proxy_impl.h
+++ b/base/message_loop_proxy_impl.h
@@ -18,7 +18,7 @@ namespace base {
class MessageLoopProxyImpl : public MessageLoopProxy,
public MessageLoop::DestructionObserver {
public:
- ~MessageLoopProxyImpl();
+ virtual ~MessageLoopProxyImpl();
// MessageLoopProxy implementation
virtual bool PostTask(const tracked_objects::Location& from_here,
@@ -33,8 +33,8 @@ class MessageLoopProxyImpl : public MessageLoopProxy,
int64 delay_ms);
virtual bool BelongsToCurrentThread();
-// MessageLoop::DestructionObserver implementation
- void WillDestroyCurrentMessageLoop();
+ // MessageLoop::DestructionObserver implementation
+ virtual void WillDestroyCurrentMessageLoop();
protected:
// Override OnDestruct so that we can delete the object on the target message
diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc
index 537c606..a196519 100644
--- a/base/message_loop_unittest.cc
+++ b/base/message_loop_unittest.cc
@@ -1576,7 +1576,7 @@ TEST(MessageLoopTest, HighResolutionTimer) {
#endif // defined(OS_WIN)
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && !defined(OS_NACL)
namespace {
@@ -1646,7 +1646,7 @@ TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) {
} // namespace
-#endif // defined(OS_POSIX)
+#endif // defined(OS_POSIX) && !defined(OS_NACL)
namespace {
class RunAtDestructionTask : public Task {
diff --git a/base/message_pump_glib.cc b/base/message_pump_glib.cc
index fa5b726..fd24285 100644
--- a/base/message_pump_glib.cc
+++ b/base/message_pump_glib.cc
@@ -315,6 +315,10 @@ void MessagePumpForUI::DidProcessEvent(GdkEvent* event) {
FOR_EACH_OBSERVER(Observer, observers_, DidProcessEvent(event));
}
+void MessagePumpForUI::Run(Delegate* delegate) {
+ RunWithDispatcher(delegate, NULL);
+}
+
void MessagePumpForUI::Quit() {
if (state_) {
state_->should_quit = true;
diff --git a/base/message_pump_glib.h b/base/message_pump_glib.h
index 06635de..c118155 100644
--- a/base/message_pump_glib.h
+++ b/base/message_pump_glib.h
@@ -62,7 +62,7 @@ class MessagePumpForUI : public MessagePump {
// is ready for processing.
virtual bool RunOnce(GMainContext* context, bool block);
- virtual void Run(Delegate* delegate) { RunWithDispatcher(delegate, NULL); }
+ virtual void Run(Delegate* delegate);
virtual void Quit();
virtual void ScheduleWork();
virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
diff --git a/base/message_pump_glib_x.cc b/base/message_pump_glib_x.cc
index 78c1799..26c4b87 100644
--- a/base/message_pump_glib_x.cc
+++ b/base/message_pump_glib_x.cc
@@ -85,6 +85,8 @@ MessagePumpGlibX::~MessagePumpGlibX() {
bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
GdkDisplay* gdisp = gdk_display_get_default();
Display* display = GDK_DISPLAY_XDISPLAY(gdisp);
+ bool should_quit = false;
+
if (XPending(display)) {
XEvent xev;
XPeekEvent(display, &xev);
@@ -95,10 +97,22 @@ bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
) {
XNextEvent(display, &xev);
- bool processed = static_cast<MessagePumpGlibXDispatcher*>
+#if defined(HAVE_XINPUT2)
+ bool have_cookie = false;
+ if (xev.type == GenericEvent &&
+ XGetEventData(xev.xgeneric.display, &xev.xcookie)) {
+ have_cookie = true;
+ }
+#endif
+
+ MessagePumpGlibXDispatcher::DispatchStatus status =
+ static_cast<MessagePumpGlibXDispatcher*>
(GetDispatcher())->Dispatch(&xev);
- if (!processed) {
+ if (status == MessagePumpGlibXDispatcher::EVENT_QUIT) {
+ should_quit = true;
+ Quit();
+ } else if (status == MessagePumpGlibXDispatcher::EVENT_IGNORED) {
DLOG(WARNING) << "Event (" << xev.type << ") not handled.";
// TODO(sad): It is necessary to put back the event so that the default
@@ -106,16 +120,29 @@ bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
// impossible to use the omnibox at the moment. However, this will
// eventually be removed once the omnibox code is updated for touchui.
XPutBackEvent(display, &xev);
+ if (gdksource_)
+ gdksource_->source_funcs->dispatch = gdkdispatcher_;
g_main_context_iteration(context, FALSE);
}
+
+#if defined(HAVE_XINPUT2)
+ if (have_cookie) {
+ XFreeEventData(xev.xgeneric.display, &xev.xcookie);
+ }
+#endif
} else {
// TODO(sad): A couple of extra events can still sneak in during this.
// Those should be sent back to the X queue from the dispatcher
// EventDispatcherX.
+ if (gdksource_)
+ gdksource_->source_funcs->dispatch = gdkdispatcher_;
g_main_context_iteration(context, FALSE);
}
}
+ if (should_quit)
+ return true;
+
bool retvalue;
if (gdksource_) {
// Replace the dispatch callback of the GDK event source temporarily so that
@@ -178,6 +205,9 @@ void MessagePumpGlibX::InitializeXInput2(void) {
return;
}
+ // TODO(sad): Here, we only setup so that the X windows created by GTK+ are
+ // setup for XInput2 events. We need a way to listen for XInput2 events for X
+ // windows created by other means (e.g. for context menus).
SetupGtkWidgetRealizeNotifier(this);
// Instead of asking X for the list of devices all the time, let's maintain a
@@ -242,6 +272,7 @@ void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
if (!pump_x->gdksource_) {
pump_x->gdksource_ = g_main_current_source();
+ pump_x->gdkdispatcher_ = pump_x->gdksource_->source_funcs->dispatch;
} else if (!pump_x->IsDispatchingEvent()) {
if (event->type != GDK_NOTHING &&
pump_x->capture_gdk_events_[event->type]) {
diff --git a/base/message_pump_glib_x.h b/base/message_pump_glib_x.h
index c6d98e3..fc3f3b1 100644
--- a/base/message_pump_glib_x.h
+++ b/base/message_pump_glib_x.h
@@ -60,6 +60,10 @@ class MessagePumpGlibX : public MessagePumpForUI {
// The event source for GDK events.
GSource* gdksource_;
+ // The default GDK event dispatcher. This is stored so that it can be restored
+ // when necessary during nested event dispatching.
+ gboolean (*gdkdispatcher_)(GSource*, GSourceFunc, void*);
+
// Indicates whether a GDK event was injected by chrome (when |true|) or if it
// was captured and being processed by GDK (when |false|).
bool dispatching_event_;
diff --git a/base/message_pump_glib_x_dispatch.h b/base/message_pump_glib_x_dispatch.h
index 95364a2..faee5b5 100644
--- a/base/message_pump_glib_x_dispatch.h
+++ b/base/message_pump_glib_x_dispatch.h
@@ -18,9 +18,18 @@ namespace base {
// GdkEvents. This class provides additional mechanism for dispatching XEvents.
class MessagePumpGlibXDispatcher : public MessagePumpForUI::Dispatcher {
public:
- // Dispatches the event. If true is returned processing continues as
- // normal. If false is returned, the nested loop exits immediately.
- virtual bool Dispatch(XEvent* xevent) = 0;
+
+ typedef enum {
+ EVENT_IGNORED, // The event was not processed.
+ EVENT_PROCESSED, // The event has been processed.
+ EVENT_QUIT // The event was processed and the message-loop should
+ // terminate.
+ } DispatchStatus;
+
+ // Dispatches the event. EVENT_IGNORED is returned if the event was ignored
+ // (i.e. not processed). EVENT_PROCESSED is returned if the event was
+ // processed. The nested loop exits immediately if EVENT_QUIT is returned.
+ virtual DispatchStatus Dispatch(XEvent* xevent) = 0;
};
} // namespace base
diff --git a/base/message_pump_mac.h b/base/message_pump_mac.h
index e016d54..c30a8ea 100644
--- a/base/message_pump_mac.h
+++ b/base/message_pump_mac.h
@@ -36,11 +36,20 @@
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
-#if defined(__OBJC__)
-@class NSAutoreleasePool;
-#else // defined(__OBJC__)
+#if !defined(__OBJC__)
class NSAutoreleasePool;
-#endif // defined(__OBJC__)
+#else // !defined(__OBJC__)
+#import <AppKit/AppKit.h>
+
+// Clients must subclass NSApplication and implement this protocol if they use
+// MessagePumpMac.
+@protocol CrAppProtocol
+// Must return true if -[NSApplication sendEvent:] is currently on the stack.
+// See the comment for |CreateAutoreleasePool()| in the cc file for why this is
+// necessary.
+- (BOOL)isHandlingSendEvent;
+@end
+#endif // !defined(__OBJC__)
namespace base {
diff --git a/base/message_pump_mac.mm b/base/message_pump_mac.mm
index 9091006..8c5461c 100644
--- a/base/message_pump_mac.mm
+++ b/base/message_pump_mac.mm
@@ -11,7 +11,6 @@
#include <limits>
-#import "base/chrome_application_mac.h"
#include "base/logging.h"
#include "base/time.h"
@@ -673,10 +672,6 @@ MessagePumpNSApplication::MessagePumpNSApplication()
void MessagePumpNSApplication::DoRun(Delegate* delegate) {
bool last_running_own_loop_ = running_own_loop_;
- // TODO(dmaclach): Get rid of this gratuitous sharedApplication.
- // Tests should be setting up their applications on their own.
- [CrApplication sharedApplication];
-
if (![NSApp isRunning]) {
running_own_loop_ = false;
// NSApplication manages autorelease pools itself when run this way.
@@ -749,12 +744,12 @@ void MessagePumpNSApplication::Quit() {
// autorelease pool stack.
//
// CrApplication is responsible for setting handlingSendEvent to true just
-// before it sends the event throught the event handling mechanism, and
+// before it sends the event through the event handling mechanism, and
// returning it to its previous value once the event has been sent.
NSAutoreleasePool* MessagePumpNSApplication::CreateAutoreleasePool() {
NSAutoreleasePool* pool = nil;
- DCHECK([NSApp isKindOfClass:[CrApplication class]]);
- if (![static_cast<CrApplication*>(NSApp) isHandlingSendEvent]) {
+ DCHECK([NSApp conformsToProtocol:@protocol(CrAppProtocol)]);
+ if (![NSApp isHandlingSendEvent]) {
pool = MessagePumpCFRunLoopBase::CreateAutoreleasePool();
}
return pool;
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index 63d9ed5..d29ed2d 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -17,6 +17,9 @@ const int FieldTrial::kNotParticipating = -1;
const int FieldTrial::kAllRemainingProbability = -2;
// static
+bool FieldTrial::enable_benchmarking_ = false;
+
+// static
const char FieldTrialList::kPersistentStringSeparator('/');
static const char kHistogramFieldTrialSeparator('_');
@@ -40,10 +43,13 @@ int FieldTrial::AppendGroup(const std::string& name,
DCHECK(group_probability <= divisor_);
DCHECK(group_probability >=0 ||
group_probability == kAllRemainingProbability);
- if (group_probability == kAllRemainingProbability)
+ if (group_probability == kAllRemainingProbability) {
accumulated_group_probability_ = divisor_;
- else
+ } else {
+ if (enable_benchmarking_)
+ group_probability = 0;
accumulated_group_probability_ += group_probability;
+ }
DCHECK(accumulated_group_probability_ <= divisor_);
if (group_ == kNotParticipating && accumulated_group_probability_ > random_) {
// This is the group that crossed the random line, so we do the assignment.
@@ -64,6 +70,12 @@ std::string FieldTrial::MakeName(const std::string& name_prefix,
return big_string.append(FieldTrialList::FindFullName(trial_name));
}
+// static
+void FieldTrial::EnableBenchmarking() {
+ DCHECK_EQ(0u, FieldTrialList::GetFieldTrialCount());
+ enable_benchmarking_ = true;
+}
+
FieldTrial::~FieldTrial() {}
//------------------------------------------------------------------------------
@@ -190,4 +202,12 @@ bool FieldTrialList::StringAugmentsState(const std::string& prior_state) {
return true;
}
+// static
+size_t FieldTrialList::GetFieldTrialCount() {
+ if (!global_)
+ return 0;
+ AutoLock auto_lock(global_->lock_);
+ return global_->registered_.size();
+}
+
} // namespace base
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h
index 348a1a7..1f0af9e 100644
--- a/base/metrics/field_trial.h
+++ b/base/metrics/field_trial.h
@@ -117,6 +117,9 @@ class FieldTrial : public RefCounted<FieldTrial> {
static std::string MakeName(const std::string& name_prefix,
const std::string& trial_name);
+ // Enable benchmarking sets field trials to a common setting.
+ static void EnableBenchmarking();
+
private:
friend class RefCounted<FieldTrial>;
@@ -148,6 +151,10 @@ class FieldTrial : public RefCounted<FieldTrial> {
// If this Trial is not a member of an group, this string is empty.
std::string group_name_;
+ // When benchmarking is enabled, field trials all revert to the 'default'
+ // bucket.
+ static bool enable_benchmarking_;
+
DISALLOW_COPY_AND_ASSIGN(FieldTrial);
};
@@ -206,6 +213,9 @@ class FieldTrialList {
return TimeTicks::Now();
}
+ // Return the number of active field trials.
+ static size_t GetFieldTrialCount();
+
private:
// Helper function should be called only while holding lock_.
FieldTrial* PreLockedFind(const std::string& name);
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 729e3b9..75df12e 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -571,6 +571,18 @@ Histogram::Inconsistencies Histogram::FindCorruption(
return static_cast<Inconsistencies>(inconsistencies);
}
+Histogram::ClassType Histogram::histogram_type() const {
+ return HISTOGRAM;
+}
+
+Histogram::Sample Histogram::ranges(size_t i) const {
+ return ranges_[i];
+}
+
+size_t Histogram::bucket_count() const {
+ return bucket_count_;
+}
+
//------------------------------------------------------------------------------
// Methods for the Histogram::SampleSet class
//------------------------------------------------------------------------------
@@ -892,12 +904,21 @@ double CustomHistogram::GetBucketSize(Count current, size_t i) const {
// provide support for all future calls.
StatisticsRecorder::StatisticsRecorder() {
DCHECK(!histograms_);
- lock_ = new Lock;
+ if (lock_ == NULL) {
+ // This will leak on purpose. It's the only way to make sure we won't race
+ // against the static uninitialization of the module while one of our
+ // static methods relying on the lock get called at an inappropriate time
+ // during the termination phase. Since it's a static data member, we will
+ // leak one per process, which would be similar to the instance allocated
+ // during static initialization and released only on process termination.
+ lock_ = new Lock;
+ }
+ AutoLock auto_lock(*lock_);
histograms_ = new HistogramMap;
}
StatisticsRecorder::~StatisticsRecorder() {
- DCHECK(histograms_);
+ DCHECK(histograms_ && lock_);
if (dump_on_exit_) {
std::string output;
@@ -905,14 +926,22 @@ StatisticsRecorder::~StatisticsRecorder() {
LOG(INFO) << output;
}
// Clean up.
- delete histograms_;
- histograms_ = NULL;
- delete lock_;
- lock_ = NULL;
+ HistogramMap* histograms = NULL;
+ {
+ AutoLock auto_lock(*lock_);
+ histograms = histograms_;
+ histograms_ = NULL;
+ }
+ delete histograms;
+ // We don't delete lock_ on purpose to avoid having to properly protect
+ // against it going away after we checked for NULL in the static methods.
}
// static
-bool StatisticsRecorder::WasStarted() {
+bool StatisticsRecorder::IsActive() {
+ if (lock_ == NULL)
+ return false;
+ AutoLock auto_lock(*lock_);
return NULL != histograms_;
}
@@ -923,10 +952,12 @@ bool StatisticsRecorder::WasStarted() {
// destroyed before assignment (when value was returned by new).
// static
void StatisticsRecorder::Register(Histogram* histogram) {
+ if (lock_ == NULL)
+ return;
+ AutoLock auto_lock(*lock_);
if (!histograms_)
return;
const std::string name = histogram->histogram_name();
- AutoLock auto_lock(*lock_);
// Avoid overwriting a previous registration.
if (histograms_->end() == histograms_->find(name))
(*histograms_)[name] = histogram;
@@ -935,7 +966,7 @@ void StatisticsRecorder::Register(Histogram* histogram) {
// static
void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
std::string* output) {
- if (!histograms_)
+ if (!IsActive())
return;
output->append("<html><head><title>About Histograms");
if (!query.empty())
@@ -959,7 +990,7 @@ void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
// static
void StatisticsRecorder::WriteGraph(const std::string& query,
std::string* output) {
- if (!histograms_)
+ if (!IsActive())
return;
if (query.length())
StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
@@ -978,9 +1009,11 @@ void StatisticsRecorder::WriteGraph(const std::string& query,
// static
void StatisticsRecorder::GetHistograms(Histograms* output) {
- if (!histograms_)
+ if (lock_ == NULL)
return;
AutoLock auto_lock(*lock_);
+ if (!histograms_)
+ return;
for (HistogramMap::iterator it = histograms_->begin();
histograms_->end() != it;
++it) {
@@ -991,9 +1024,11 @@ void StatisticsRecorder::GetHistograms(Histograms* output) {
bool StatisticsRecorder::FindHistogram(const std::string& name,
scoped_refptr<Histogram>* histogram) {
- if (!histograms_)
+ if (lock_ == NULL)
return false;
AutoLock auto_lock(*lock_);
+ if (!histograms_)
+ return false;
HistogramMap::iterator it = histograms_->find(name);
if (histograms_->end() == it)
return false;
@@ -1004,7 +1039,11 @@ bool StatisticsRecorder::FindHistogram(const std::string& name,
// private static
void StatisticsRecorder::GetSnapshot(const std::string& query,
Histograms* snapshot) {
+ if (lock_ == NULL)
+ return;
AutoLock auto_lock(*lock_);
+ if (!histograms_)
+ return;
for (HistogramMap::iterator it = histograms_->begin();
histograms_->end() != it;
++it) {
diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h
index b87c891..6b09aa3 100644
--- a/base/metrics/histogram.h
+++ b/base/metrics/histogram.h
@@ -403,13 +403,13 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
//----------------------------------------------------------------------------
// Accessors for factory constuction, serialization and testing.
//----------------------------------------------------------------------------
- virtual ClassType histogram_type() const { return HISTOGRAM; }
+ virtual ClassType histogram_type() const;
const std::string& histogram_name() const { return histogram_name_; }
Sample declared_min() const { return declared_min_; }
Sample declared_max() const { return declared_max_; }
- virtual Sample ranges(size_t i) const { return ranges_[i];}
+ virtual Sample ranges(size_t i) const;
Sample range_checksum() const { return range_checksum_; }
- virtual size_t bucket_count() const { return bucket_count_; }
+ virtual size_t bucket_count() const;
// Snapshot the current complete set of sample data.
// Override with atomic/locked snapshot if needed.
virtual void SnapshotSample(SampleSet* sample) const;
@@ -643,7 +643,7 @@ class StatisticsRecorder {
~StatisticsRecorder();
// Find out if histograms can now be registered into our list.
- static bool WasStarted();
+ static bool IsActive();
// Register, or add a new histogram to the collection of statistics.
static void Register(Histogram* histogram);
diff --git a/base/mime_util_xdg.cc b/base/mime_util_xdg.cc
index 5dc4960..8be1d0d 100644
--- a/base/mime_util_xdg.cc
+++ b/base/mime_util_xdg.cc
@@ -28,6 +28,9 @@ class IconTheme;
class MimeUtilConstants {
public:
+ static MimeUtilConstants* GetInstance() {
+ return Singleton<MimeUtilConstants>::get();
+ }
// In seconds, specified by icon theme specs.
const int kUpdateInterval;
@@ -157,7 +160,7 @@ IconTheme::IconTheme(const std::string& name)
std::map<FilePath, int>::iterator iter;
FilePath theme_path;
std::map<FilePath, int>* icon_dirs =
- Singleton<MimeUtilConstants>::get()->icon_dirs_;
+ MimeUtilConstants::GetInstance()->icon_dirs_;
for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) {
theme_path = iter->first.Append(name);
if (!file_util::DirectoryExists(theme_path))
@@ -218,7 +221,7 @@ FilePath IconTheme::GetIconPath(const std::string& icon_name, int size,
IconTheme* IconTheme::LoadTheme(const std::string& theme_name) {
scoped_ptr<IconTheme> theme;
std::map<std::string, IconTheme*>* icon_themes =
- Singleton<MimeUtilConstants>::get()->icon_themes_;
+ MimeUtilConstants::GetInstance()->icon_themes_;
if (icon_themes->find(theme_name) != icon_themes->end()) {
theme.reset((*icon_themes)[theme_name]);
} else {
@@ -235,7 +238,7 @@ FilePath IconTheme::GetIconPathUnderSubdir(const std::string& icon_name,
FilePath icon_path;
std::list<FilePath>::iterator dir_iter;
std::vector<std::string>* icon_formats =
- &Singleton<MimeUtilConstants>::get()->icon_formats_;
+ &MimeUtilConstants::GetInstance()->icon_formats_;
for (dir_iter = dirs_.begin(); dir_iter != dirs_.end(); ++dir_iter) {
for (size_t i = 0; i < icon_formats->size(); ++i) {
icon_path = dir_iter->Append(subdir);
@@ -383,7 +386,7 @@ bool IconTheme::SetDirectories(const std::string& dirs) {
void TryAddIconDir(const FilePath& dir) {
if (!file_util::DirectoryExists(dir))
return;
- (*Singleton<MimeUtilConstants>::get()->icon_dirs_)[dir] = 0;
+ (*MimeUtilConstants::GetInstance()->icon_dirs_)[dir] = 0;
}
// For a xdg directory |dir|, add the appropriate icon sub-directories.
@@ -396,7 +399,7 @@ void AddXDGDataDir(const FilePath& dir) {
// Add all the xdg icon directories.
void InitIconDir() {
- Singleton<MimeUtilConstants>::get()->icon_dirs_->clear();
+ MimeUtilConstants::GetInstance()->icon_dirs_->clear();
FilePath home = file_util::GetHomeDir();
if (!home.empty()) {
FilePath legacy_data_dir(home);
@@ -435,7 +438,7 @@ void EnsureUpdated() {
struct timeval t;
gettimeofday(&t, NULL);
time_t now = t.tv_sec;
- MimeUtilConstants* constants = Singleton<MimeUtilConstants>::get();
+ MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
if (constants->last_check_time_ == 0) {
constants->icon_dirs_ = new std::map<FilePath, int>;
@@ -453,7 +456,7 @@ void EnsureUpdated() {
// Find a fallback icon if we cannot find it in the default theme.
FilePath LookupFallbackIcon(const std::string& icon_name) {
FilePath icon;
- MimeUtilConstants* constants = Singleton<MimeUtilConstants>::get();
+ MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
std::map<FilePath, int>::iterator iter;
std::map<FilePath, int>* icon_dirs = constants->icon_dirs_;
std::vector<std::string>* icon_formats = &constants->icon_formats_;
@@ -470,7 +473,7 @@ FilePath LookupFallbackIcon(const std::string& icon_name) {
// Initialize the list of default themes.
void InitDefaultThemes() {
IconTheme** default_themes =
- Singleton<MimeUtilConstants>::get()->default_themes_;
+ MimeUtilConstants::GetInstance()->default_themes_;
char* env = getenv("KDE_FULL_SESSION");
if (env) {
@@ -498,7 +501,7 @@ void InitDefaultThemes() {
} else {
// Assume it's Gnome and use GTK to figure out the theme.
default_themes[1] = IconTheme::LoadTheme(
- Singleton<MimeUtilConstants>::get()->gtk_theme_name_);
+ MimeUtilConstants::GetInstance()->gtk_theme_name_);
default_themes[2] = IconTheme::LoadTheme("gnome");
}
// hicolor needs to be last per icon theme spec.
@@ -518,7 +521,7 @@ void InitDefaultThemes() {
// Try to find an icon with the name |icon_name| that's |size| pixels.
FilePath LookupIconInDefaultTheme(const std::string& icon_name, int size) {
EnsureUpdated();
- MimeUtilConstants* constants = Singleton<MimeUtilConstants>::get();
+ MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
std::map<std::string, IconTheme*>* icon_themes = constants->icon_themes_;
if (icon_themes->size() == 0)
InitDefaultThemes();
@@ -558,7 +561,7 @@ void DetectGtkTheme() {
// If the theme name is already loaded, do nothing. Chrome doesn't respond
// to changes in the system theme, so we never need to set this more than
// once.
- if (!Singleton<MimeUtilConstants>::get()->gtk_theme_name_.empty())
+ if (!MimeUtilConstants::GetInstance()->gtk_theme_name_.empty())
return;
// We should only be called on the UI thread.
@@ -568,7 +571,7 @@ void DetectGtkTheme() {
g_object_get(gtk_settings_get_default(),
"gtk-icon-theme-name",
&gtk_theme_name, NULL);
- Singleton<MimeUtilConstants>::get()->gtk_theme_name_.assign(gtk_theme_name);
+ MimeUtilConstants::GetInstance()->gtk_theme_name_.assign(gtk_theme_name);
g_free(gtk_theme_name);
}
diff --git a/base/nsimage_cache_mac.h b/base/nsimage_cache_mac.h
deleted file mode 100644
index b13eac9..0000000
--- a/base/nsimage_cache_mac.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2009 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_NSIMAGE_CACHE_MAC_H_
-#define BASE_NSIMAGE_CACHE_MAC_H_
-#pragma once
-
-#ifdef __OBJC__
-@class NSImage;
-@class NSString;
-#else
-class NSImage;
-class NSString;
-#endif
-
-namespace nsimage_cache {
-
-// Returns an autoreleased image from the main app bundle
-// (mac_util::MainAppBundle()) with the given name, and keeps it in memory so
-// future fetches are fast.
-// NOTE:
-// - This should only be called on the main thread.
-// - The caller should retain the image if they want to keep it around, as
-// the cache could have limit on size/lifetime, etc.
-NSImage* ImageNamed(NSString* name);
-
-// Clears the cache.
-void Clear(void);
-
-} // namespace nsimage_cache
-
-#endif // BASE_NSIMAGE_CACHE_MAC_H_
diff --git a/base/nsimage_cache_mac.mm b/base/nsimage_cache_mac.mm
deleted file mode 100644
index e693ed4..0000000
--- a/base/nsimage_cache_mac.mm
+++ /dev/null
@@ -1,73 +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/nsimage_cache_mac.h"
-
-#import <AppKit/AppKit.h>
-
-#include "base/logging.h"
-#include "base/mac_util.h"
-
-// When C++ exceptions are disabled, the C++ library defines |try| and
-// |catch| so as to allow exception-expecting C++ code to build properly when
-// language support for exceptions is not present. These macros interfere
-// with the use of |@try| and |@catch| in Objective-C files such as this one.
-// Undefine these macros here, after everything has been #included, since
-// there will be no C++ uses and only Objective-C uses from this point on.
-#undef try
-#undef catch
-
-namespace nsimage_cache {
-
-static NSMutableDictionary* image_cache = nil;
-
-NSImage* ImageNamed(NSString* name) {
- DCHECK(name);
-
- // NOTE: to make this thread safe, we'd have to sync on the cache and
- // also force all the bundle calls on the main thread.
-
- if (!image_cache) {
- image_cache = [[NSMutableDictionary alloc] init];
- DCHECK(image_cache);
- }
-
- NSImage* result = [image_cache objectForKey:name];
- if (!result) {
- DVLOG_IF(1, [[name pathExtension] length] == 0) << "Suggest including the "
- "extension in the image name";
-
- NSString* path = [mac_util::MainAppBundle() pathForImageResource:name];
- if (path) {
- @try {
- result = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
- if (result) {
- // Auto-template images with names ending in "Template".
- NSString* extensionlessName = [name stringByDeletingPathExtension];
- if ([extensionlessName hasSuffix:@"Template"])
- [result setTemplate:YES];
-
- [image_cache setObject:result forKey:name];
- }
- }
- @catch (id err) {
- DLOG(ERROR) << "Failed to load the image for name '"
- << [name UTF8String] << "' from path '" << [path UTF8String]
- << "', error: " << [[err description] UTF8String];
- result = nil;
- }
- }
- }
-
- // TODO: if we ever limit the cache size, this should retain & autorelease
- // the image.
- return result;
-}
-
-void Clear(void) {
- // NOTE: to make this thread safe, we'd have to sync on the cache.
- [image_cache removeAllObjects];
-}
-
-} // namespace nsimage_cache
diff --git a/base/nss_util.cc b/base/nss_util.cc
index 580fb60..36394da 100644
--- a/base/nss_util.cc
+++ b/base/nss_util.cc
@@ -333,6 +333,10 @@ void EnsureNSSInit() {
g_nss_singleton.Get();
}
+bool CheckNSSVersion(const char* version) {
+ return !!NSS_VersionCheck(version);
+}
+
#if defined(USE_NSS)
bool OpenTestNSSDB(const FilePath& path, const char* description) {
return g_nss_singleton.Get().OpenTestNSSDB(path, description);
diff --git a/base/nss_util.h b/base/nss_util.h
index 15b624c..d1e36ac 100644
--- a/base/nss_util.h
+++ b/base/nss_util.h
@@ -30,6 +30,10 @@ void EnsureNSPRInit();
// ever be initialized once. NSS will be properly shut down on program exit.
void EnsureNSSInit();
+// Check if the current NSS version is greater than or equals to |version|.
+// A sample version string is "3.12.3".
+bool CheckNSSVersion(const char* version);
+
#if defined(OS_CHROMEOS)
// Open the r/w nssdb that's stored inside the user's encrypted home directory.
void OpenPersistentNSSDB();
diff --git a/base/openssl_util.cc b/base/openssl_util.cc
index 5cfc34a..bc174fa 100644
--- a/base/openssl_util.cc
+++ b/base/openssl_util.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/scoped_vector.h"
#include "base/singleton.h"
+#include "base/string_piece.h"
namespace base {
@@ -23,7 +24,7 @@ unsigned long CurrentThreadId() {
// Singleton for initializing and cleaning up the OpenSSL library.
class OpenSSLInitSingleton {
public:
- static OpenSSLInitSingleton* Get() {
+ static OpenSSLInitSingleton* GetInstance() {
// We allow the SSL environment to leak for multiple reasons:
// - it is used from a non-joinable worker thread that is not stopped on
// shutdown, hence may still be using OpenSSL library after the AtExit
@@ -57,7 +58,7 @@ class OpenSSLInitSingleton {
}
static void LockingCallback(int mode, int n, const char* file, int line) {
- OpenSSLInitSingleton::Get()->OnLockingCallback(mode, n, file, line);
+ OpenSSLInitSingleton::GetInstance()->OnLockingCallback(mode, n, file, line);
}
void OnLockingCallback(int mode, int n, const char* file, int line) {
@@ -74,27 +75,36 @@ class OpenSSLInitSingleton {
DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton);
};
+// Callback routine for OpenSSL to print error messages. |str| is a
+// NULL-terminated string of length |len| containing diagnostic information
+// such as the library, function and reason for the error, the file and line
+// where the error originated, plus potentially any context-specific
+// information about the error. |context| contains a pointer to user-supplied
+// data, which is currently unused.
+// If this callback returns a value <= 0, OpenSSL will stop processing the
+// error queue and return, otherwise it will continue calling this function
+// until all errors have been removed from the queue.
+int OpenSSLErrorCallback(const char* str, size_t len, void* context) {
+ DVLOG(1) << "\t" << StringPiece(str, len);
+ return 1;
+}
+
} // namespace
void EnsureOpenSSLInit() {
- (void)OpenSSLInitSingleton::Get();
+ (void)OpenSSLInitSingleton::GetInstance();
}
void ClearOpenSSLERRStack(const tracked_objects::Location& location) {
if (logging::DEBUG_MODE && VLOG_IS_ON(1)) {
- int error_num = ERR_get_error();
+ int error_num = ERR_peek_error();
if (error_num == 0)
return;
std::string message;
location.Write(true, true, &message);
DVLOG(1) << "OpenSSL ERR_get_error stack from " << message;
- char buf[140];
- do {
- ERR_error_string_n(error_num, buf, arraysize(buf));
- DVLOG(1) << "\t" << error_num << ": " << buf;
- error_num = ERR_get_error();
- } while (error_num != 0);
+ ERR_print_errors_cb(&OpenSSLErrorCallback, NULL);
} else {
ERR_clear_error();
}
diff --git a/base/openssl_util.h b/base/openssl_util.h
index 60cb0b7..9ce7f81 100644
--- a/base/openssl_util.h
+++ b/base/openssl_util.h
@@ -18,7 +18,9 @@ class ScopedOpenSSL {
public:
ScopedOpenSSL() : ptr_(NULL) { }
explicit ScopedOpenSSL(T* ptr) : ptr_(ptr) { }
- ~ScopedOpenSSL() { if (ptr_) (*destructor)(ptr_); }
+ ~ScopedOpenSSL() {
+ reset(NULL);
+ }
T* get() const { return ptr_; }
void reset(T* ptr) {
diff --git a/base/path_service.cc b/base/path_service.cc
index 8660c42..56ce5fa 100644
--- a/base/path_service.cc
+++ b/base/path_service.cc
@@ -13,9 +13,9 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
#include "base/lock.h"
#include "base/logging.h"
-#include "base/singleton.h"
namespace base {
bool PathProvider(int key, FilePath* result);
@@ -118,8 +118,10 @@ struct PathData {
}
};
+static base::LazyInstance<PathData> g_path_data(base::LINKER_INITIALIZED);
+
static PathData* GetPathData() {
- return Singleton<PathData>::get();
+ return g_path_data.Pointer();
}
} // namespace
@@ -203,18 +205,6 @@ bool PathService::Get(int key, FilePath* result) {
return true;
}
-#if defined(OS_WIN)
-// static
-bool PathService::Get(int key, std::wstring* result) {
- // Deprecated compatibility function.
- FilePath path;
- if (!Get(key, &path))
- return false;
- *result = path.ToWStringHack();
- return true;
-}
-#endif
-
bool PathService::Override(int key, const FilePath& path) {
PathData* path_data = GetPathData();
DCHECK(path_data);
diff --git a/base/path_service.h b/base/path_service.h
index 4d99cdc..edaa5e3 100644
--- a/base/path_service.h
+++ b/base/path_service.h
@@ -27,11 +27,6 @@ class PathService {
// Returns true if the directory or file was successfully retrieved. On
// failure, 'path' will not be changed.
static bool Get(int key, FilePath* path);
-#if defined(OS_WIN)
- // This version, producing a wstring, is deprecated and only kept around
- // until we can fix all callers.
- static bool Get(int key, std::wstring* path);
-#endif
// Overrides the path to a special directory or file. This cannot be used to
// change the value of DIR_CURRENT, but that should be obvious. Also, if the
diff --git a/base/pickle.cc b/base/pickle.cc
index 7745527..3f376e3 100644
--- a/base/pickle.cc
+++ b/base/pickle.cc
@@ -406,9 +406,6 @@ const char* Pickle::FindNext(size_t header_size,
DCHECK(header_size == AlignInt(header_size, sizeof(uint32)));
DCHECK(header_size <= static_cast<size_t>(kPayloadUnit));
- if (static_cast<size_t>(end - start) < sizeof(Header))
- return NULL;
-
const Header* hdr = reinterpret_cast<const Header*>(start);
const char* payload_base = start + header_size;
const char* payload_end = payload_base + hdr->payload_size;
diff --git a/base/pickle.h b/base/pickle.h
index 03f0af1..6006e62 100644
--- a/base/pickle.h
+++ b/base/pickle.h
@@ -236,7 +236,6 @@ class Pickle {
FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
- FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
FRIEND_TEST_ALL_PREFIXES(PickleTest, IteratorHasRoom);
};
diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc
index 39eaa1b..fdc0664 100644
--- a/base/pickle_unittest.cc
+++ b/base/pickle_unittest.cc
@@ -171,17 +171,6 @@ TEST(PickleTest, FindNext) {
EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end + 1));
}
-TEST(PickleTest, FindNextWithIncompleteHeader) {
- size_t header_size = sizeof(Pickle::Header);
- scoped_array<char> buffer(new char[header_size - 1]);
- memset(buffer.get(), 0x1, header_size - 1);
-
- const char* start = buffer.get();
- const char* end = start + header_size - 1;
-
- EXPECT_TRUE(NULL == Pickle::FindNext(header_size, start, end));
-}
-
TEST(PickleTest, IteratorHasRoom) {
Pickle pickle;
EXPECT_TRUE(pickle.WriteInt(1));
diff --git a/base/platform_thread_mac.mm b/base/platform_thread_mac.mm
index 34afea7..36e08be 100644
--- a/base/platform_thread_mac.mm
+++ b/base/platform_thread_mac.mm
@@ -9,21 +9,6 @@
#include "base/logging.h"
-// A simple class that demonstrates our impressive ability to do nothing.
-@interface NoOp : NSObject
-
-// Does the deed. Or does it?
-+ (void)noOp;
-
-@end
-
-@implementation NoOp
-
-+ (void)noOp {
-}
-
-@end
-
namespace base {
// If Cocoa is to be used on more than one thread, it must know that the
@@ -37,8 +22,9 @@ namespace base {
void InitThreading() {
static BOOL multithreaded = [NSThread isMultiThreaded];
if (!multithreaded) {
- [NSThread detachNewThreadSelector:@selector(noOp)
- toTarget:[NoOp class]
+ // +[NSObject class] is idempotent.
+ [NSThread detachNewThreadSelector:@selector(class)
+ toTarget:[NSObject class]
withObject:nil];
multithreaded = YES;
diff --git a/base/platform_thread_posix.cc b/base/platform_thread_posix.cc
index e442e9c..9807ac6 100644
--- a/base/platform_thread_posix.cc
+++ b/base/platform_thread_posix.cc
@@ -219,5 +219,9 @@ bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
// static
void PlatformThread::Join(PlatformThreadHandle thread_handle) {
+ // Joining another thread may block the current thread for a long time, since
+ // the thread referred to by |thread_handle| may still be running long-lived /
+ // blocking tasks.
+ base::ThreadRestrictions::AssertIOAllowed();
pthread_join(thread_handle, NULL);
}
diff --git a/base/platform_thread_win.cc b/base/platform_thread_win.cc
index e5afc52..ac8a5db 100644
--- a/base/platform_thread_win.cc
+++ b/base/platform_thread_win.cc
@@ -125,6 +125,14 @@ bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
// static
void PlatformThread::Join(PlatformThreadHandle thread_handle) {
DCHECK(thread_handle);
+ // TODO(willchan): Enable this check once I can get it to work for Windows
+ // shutdown.
+ // Joining another thread may block the current thread for a long time, since
+ // the thread referred to by |thread_handle| may still be running long-lived /
+ // blocking tasks.
+#if 0
+ base::ThreadRestrictions::AssertIOAllowed();
+#endif
// Wait for the thread to exit. It should already have terminated but make
// sure this assumption is valid.
diff --git a/base/process_util.cc b/base/process_util.cc
index 6293740..7b2935d 100644
--- a/base/process_util.cc
+++ b/base/process_util.cc
@@ -11,7 +11,7 @@ ProcessEntry::ProcessEntry() {}
ProcessEntry::~ProcessEntry() {}
#endif
-int GetProcessCount(const std::wstring& executable_name,
+int GetProcessCount(const FilePath::StringType& executable_name,
const ProcessFilter* filter) {
int count = 0;
NamedProcessIterator iter(executable_name, filter);
@@ -20,7 +20,7 @@ int GetProcessCount(const std::wstring& executable_name,
return count;
}
-bool KillProcesses(const std::wstring& executable_name, int exit_code,
+bool KillProcesses(const FilePath::StringType& executable_name, int exit_code,
const ProcessFilter* filter) {
bool result = true;
NamedProcessIterator iter(executable_name, filter);
@@ -56,10 +56,10 @@ ProcessIterator::ProcessEntries ProcessIterator::Snapshot() {
return found;
}
-NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name,
- const ProcessFilter* filter)
- : ProcessIterator(filter),
- executable_name_(executable_name) {
+NamedProcessIterator::NamedProcessIterator(
+ const FilePath::StringType& executable_name,
+ const ProcessFilter* filter) : ProcessIterator(filter),
+ executable_name_(executable_name) {
}
NamedProcessIterator::~NamedProcessIterator() {
diff --git a/base/process_util.h b/base/process_util.h
index ca43289..ce4b0bb 100644
--- a/base/process_util.h
+++ b/base/process_util.h
@@ -34,10 +34,10 @@ typedef struct _malloc_zone_t malloc_zone_t;
#include <vector>
#include "base/file_descriptor_shuffle.h"
+#include "base/file_path.h"
#include "base/process.h"
class CommandLine;
-class FilePath;
namespace base {
@@ -118,13 +118,15 @@ const uint32 kProcessAccessQueryLimitedInfomation = 0;
const uint32 kProcessAccessWaitForTermination = 0;
#endif // defined(OS_POSIX)
-// A minimalistic but hopefully cross-platform set of exit codes.
-// Do not change the enumeration values or you will break third-party
-// installers.
-enum {
- PROCESS_END_NORMAL_TERMINATION = 0,
- PROCESS_END_KILLED_BY_USER = 1,
- PROCESS_END_PROCESS_WAS_HUNG = 2
+// Return status values from GetTerminationStatus. Don't use these as
+// exit code arguments to KillProcess*(), use platform/application
+// specific values instead.
+enum TerminationStatus {
+ TERMINATION_STATUS_NORMAL_TERMINATION, // zero exit status
+ TERMINATION_STATUS_ABNORMAL_TERMINATION, // non-zero exit status
+ TERMINATION_STATUS_PROCESS_WAS_KILLED, // e.g. SIGKILL or task manager kill
+ TERMINATION_STATUS_PROCESS_CRASHED, // e.g. Segmentation fault
+ TERMINATION_STATUS_STILL_RUNNING // child hasn't exited yet
};
// Returns the id of the current process.
@@ -180,7 +182,7 @@ bool AdjustOOMScore(ProcessId process, int score);
#endif
#if defined(OS_POSIX)
-// Close all file descriptors, expect those which are a destination in the
+// Close all file descriptors, except those which are a destination in the
// given multimap. Only call this function in a child process where you know
// that there aren't any other threads.
void CloseSuperfluousFds(const InjectiveMultimap& saved_map);
@@ -320,7 +322,7 @@ class ProcessFilter {
// Returns the number of processes on the machine that are running from the
// given executable name. If filter is non-null, then only processes selected
// by the filter will be counted.
-int GetProcessCount(const std::wstring& executable_name,
+int GetProcessCount(const FilePath::StringType& executable_name,
const ProcessFilter* filter);
// Attempts to kill all the processes on the current machine that were launched
@@ -328,7 +330,7 @@ int GetProcessCount(const std::wstring& executable_name,
// filter is non-null, then only processes selected by the filter are killed.
// Returns true if all processes were able to be killed off, false if at least
// one couldn't be killed.
-bool KillProcesses(const std::wstring& executable_name, int exit_code,
+bool KillProcesses(const FilePath::StringType& executable_name, int exit_code,
const ProcessFilter* filter);
// Attempts to kill the process identified by the given process
@@ -347,10 +349,15 @@ bool KillProcessGroup(ProcessHandle process_group_id);
bool KillProcessById(ProcessId process_id, int exit_code, bool wait);
#endif
-// Get the termination status (exit code) of the process and return true if the
-// status indicates the process crashed. |child_exited| is set to true iff the
-// child process has terminated. (|child_exited| may be NULL.)
-bool DidProcessCrash(bool* child_exited, ProcessHandle handle);
+// Get the termination status of the process by interpreting the
+// circumstances of the child process' death. |exit_code| is set to
+// the status returned by waitpid() on POSIX, and from
+// GetExitCodeProcess() on Windows. |exit_code| may be NULL if the
+// caller is not interested in it. Note that on Linux, this function
+// will only return a useful result the first time it is called after
+// the child exits (because it will reap the child and the information
+// will no longer be available).
+TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code);
// Waits for process to exit. In POSIX systems, if the process hasn't been
// signaled then puts the exit code in |exit_code|; otherwise it's considered
@@ -370,7 +377,7 @@ bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code,
// is non-null, then only processes selected by the filter are waited on.
// Returns after all processes have exited or wait_milliseconds have expired.
// Returns true if all the processes exited, false otherwise.
-bool WaitForProcessesToExit(const std::wstring& executable_name,
+bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
int64 wait_milliseconds,
const ProcessFilter* filter);
@@ -389,7 +396,7 @@ bool CrashAwareSleep(ProcessHandle handle, int64 wait_milliseconds);
// on. Killed processes are ended with the given exit code. Returns false if
// any processes needed to be killed, true if they all exited cleanly within
// the wait_milliseconds delay.
-bool CleanupProcesses(const std::wstring& executable_name,
+bool CleanupProcesses(const FilePath::StringType& executable_name,
int64 wait_milliseconds,
int exit_code,
const ProcessFilter* filter);
@@ -450,7 +457,7 @@ class ProcessIterator {
// until it returns false.
class NamedProcessIterator : public ProcessIterator {
public:
- NamedProcessIterator(const std::wstring& executable_name,
+ NamedProcessIterator(const FilePath::StringType& executable_name,
const ProcessFilter* filter);
virtual ~NamedProcessIterator();
@@ -458,7 +465,7 @@ class NamedProcessIterator : public ProcessIterator {
virtual bool IncludeEntry();
private:
- std::wstring executable_name_;
+ FilePath::StringType executable_name_;
DISALLOW_COPY_AND_ASSIGN(NamedProcessIterator);
};
diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc
index 6138c07..670de6a 100644
--- a/base/process_util_linux.cc
+++ b/base/process_util_linux.cc
@@ -111,13 +111,12 @@ FilePath GetProcessExecutablePath(ProcessHandle process) {
FilePath stat_file("/proc");
stat_file = stat_file.Append(base::IntToString(process));
stat_file = stat_file.Append("exe");
- char exename[2048];
- ssize_t len = readlink(stat_file.value().c_str(), exename, sizeof(exename));
- if (len < 1) {
+ FilePath exe_name;
+ if (!file_util::ReadSymbolicLink(stat_file, &exe_name)) {
// No such process. Happens frequently in e.g. TerminateAllChromeProcesses
return FilePath();
}
- return FilePath(std::string(exename, len));
+ return exe_name;
}
ProcessIterator::ProcessIterator(const ProcessFilter* filter)
@@ -221,8 +220,7 @@ bool ProcessIterator::CheckForNextProcess() {
}
bool NamedProcessIterator::IncludeEntry() {
- // TODO(port): make this also work for non-ASCII filenames
- if (WideToASCII(executable_name_) != entry().exe_file())
+ if (executable_name_ != entry().exe_file())
return false;
return ProcessIterator::IncludeEntry();
}
@@ -320,13 +318,20 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
// Synchronously reading files in /proc is safe.
base::ThreadRestrictions::ScopedAllowIO allow_io;
- FilePath stat_file =
- FilePath("/proc").Append(base::IntToString(process_)).Append("smaps");
+ FilePath proc_dir = FilePath("/proc").Append(base::IntToString(process_));
std::string smaps;
int private_kb = 0;
int pss_kb = 0;
bool have_pss = false;
- if (file_util::ReadFileToString(stat_file, &smaps) && smaps.length() > 0) {
+ bool ret;
+
+ {
+ FilePath smaps_file = proc_dir.Append("smaps");
+ // Synchronously reading files in /proc is safe.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ ret = file_util::ReadFileToString(smaps_file, &smaps);
+ }
+ if (ret && smaps.length() > 0) {
const std::string private_prefix = "Private_";
const std::string pss_prefix = "Pss";
StringTokenizer tokenizer(smaps, ":\n");
@@ -364,10 +369,14 @@ bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
if (page_size_kb <= 0)
return false;
- stat_file =
- FilePath("/proc").Append(base::IntToString(process_)).Append("statm");
std::string statm;
- if (!file_util::ReadFileToString(stat_file, &statm) || statm.length() == 0)
+ {
+ FilePath statm_file = proc_dir.Append("statm");
+ // Synchronously reading files in /proc is safe.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ ret = file_util::ReadFileToString(statm_file, &statm);
+ }
+ if (!ret || statm.length() == 0)
return false;
std::vector<std::string> statm_vec;
diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm
index b167aa2..aa0f14d 100644
--- a/base/process_util_mac.mm
+++ b/base/process_util_mac.mm
@@ -10,6 +10,8 @@
#include <dlfcn.h>
#include <mach/mach.h>
#include <mach/mach_init.h>
+#include <mach/mach_vm.h>
+#include <mach/shared_region.h>
#include <mach/task.h>
#include <malloc/malloc.h>
#import <objc/runtime.h>
@@ -25,6 +27,7 @@
#include "base/debug/debugger.h"
#include "base/eintr_wrapper.h"
+#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/sys_info.h"
@@ -166,7 +169,7 @@ bool ProcessIterator::CheckForNextProcess() {
}
bool NamedProcessIterator::IncludeEntry() {
- return (SysWideToUTF8(executable_name_) == entry().exe_file() &&
+ return (executable_name_ == entry().exe_file() &&
ProcessIterator::IncludeEntry());
}
@@ -235,13 +238,130 @@ size_t ProcessMetrics::GetPeakWorkingSetSize() const {
return 0;
}
-// OSX appears to use a different system to get its memory.
+static bool GetCPUTypeForProcess(pid_t pid, cpu_type_t* cpu_type) {
+ size_t len = sizeof(*cpu_type);
+ int result = sysctlbyname("sysctl.proc_cputype",
+ cpu_type,
+ &len,
+ NULL,
+ 0);
+ if (result != 0) {
+ PLOG(ERROR) << "sysctlbyname(""sysctl.proc_cputype"")";
+ return false;
+ }
+
+ return true;
+}
+
+static bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) {
+ if (type == CPU_TYPE_I386)
+ return addr >= SHARED_REGION_BASE_I386 &&
+ addr < (SHARED_REGION_BASE_I386 + SHARED_REGION_SIZE_I386);
+ else if (type == CPU_TYPE_X86_64)
+ return addr >= SHARED_REGION_BASE_X86_64 &&
+ addr < (SHARED_REGION_BASE_X86_64 + SHARED_REGION_SIZE_X86_64);
+ else
+ return false;
+}
+
+// This is a rough approximation of the algorithm that libtop uses.
+// private_bytes is the size of private resident memory.
+// shared_bytes is the size of shared resident memory.
bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
size_t* shared_bytes) {
+ kern_return_t kr;
+ size_t private_pages_count = 0;
+ size_t shared_pages_count = 0;
+
+ if (!private_bytes && !shared_bytes)
+ return true;
+
+ mach_port_t task = TaskForPid(process_);
+ if (task == MACH_PORT_NULL) {
+ LOG(ERROR) << "Invalid process";
+ return false;
+ }
+
+ cpu_type_t cpu_type;
+ if (!GetCPUTypeForProcess(process_, &cpu_type))
+ return false;
+
+ // The same region can be referenced multiple times. To avoid double counting
+ // we need to keep track of which regions we've already counted.
+ base::hash_set<int> seen_objects;
+
+ // We iterate through each VM region in the task's address map. For shared
+ // memory we add up all the pages that are marked as shared. Like libtop we
+ // try to avoid counting pages that are also referenced by other tasks. Since
+ // we don't have access to the VM regions of other tasks the only hint we have
+ // is if the address is in the shared region area.
+ //
+ // Private memory is much simpler. We simply count the pages that are marked
+ // as private or copy on write (COW).
+ //
+ // See libtop_update_vm_regions in
+ // http://www.opensource.apple.com/source/top/top-67/libtop.c
+ mach_vm_size_t size = 0;
+ for (mach_vm_address_t address = MACH_VM_MIN_ADDRESS;; address += size) {
+ vm_region_top_info_data_t info;
+ mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT;
+ mach_port_t object_name;
+ kr = mach_vm_region(task,
+ &address,
+ &size,
+ VM_REGION_TOP_INFO,
+ (vm_region_info_t)&info,
+ &info_count,
+ &object_name);
+ if (kr == KERN_INVALID_ADDRESS) {
+ // We're at the end of the address space.
+ break;
+ } else if (kr != KERN_SUCCESS) {
+ LOG(ERROR) << "Calling mach_vm_region failed with error: "
+ << mach_error_string(kr);
+ return false;
+ }
+
+ if (IsAddressInSharedRegion(address, cpu_type) &&
+ info.share_mode != SM_PRIVATE)
+ continue;
+
+ if (info.share_mode == SM_COW && info.ref_count == 1)
+ info.share_mode = SM_PRIVATE;
+
+ switch (info.share_mode) {
+ case SM_PRIVATE:
+ private_pages_count += info.private_pages_resident;
+ private_pages_count += info.shared_pages_resident;
+ break;
+ case SM_COW:
+ private_pages_count += info.private_pages_resident;
+ // Fall through
+ case SM_SHARED:
+ if (seen_objects.count(info.obj_id) == 0) {
+ // Only count the first reference to this region.
+ seen_objects.insert(info.obj_id);
+ shared_pages_count += info.shared_pages_resident;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ vm_size_t page_size;
+ kr = host_page_size(task, &page_size);
+ if (kr != KERN_SUCCESS) {
+ LOG(ERROR) << "Failed to fetch host page size, error: "
+ << mach_error_string(kr);
+ return false;
+ }
+
if (private_bytes)
- *private_bytes = 0;
+ *private_bytes = private_pages_count * page_size;
if (shared_bytes)
- *shared_bytes = 0;
+ *shared_bytes = shared_pages_count * page_size;
+
return true;
}
@@ -596,7 +716,7 @@ void EnableTerminationOnOutOfMemory() {
!g_old_valloc_purgeable && !g_old_realloc_purgeable &&
!g_old_memalign_purgeable) << "Old allocators unexpectedly non-null";
- // See http://trac.webkit.org/changeset/53362/trunk/WebKitTools/DumpRenderTree/mac
+ // See http://trac.webkit.org/changeset/53362/trunk/Tools/DumpRenderTree/mac
bool zone_allocators_protected = darwin_version > 10;
ChromeMallocZone* default_zone =
diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc
index 43096c0..f31ffdd 100644
--- a/base/process_util_posix.cc
+++ b/base/process_util_posix.cc
@@ -26,6 +26,7 @@
#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "base/stringprintf.h"
+#include "base/thread_restrictions.h"
#include "base/time.h"
#include "base/waitable_event.h"
@@ -241,6 +242,8 @@ bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
sleep_ms *= 2;
}
+ // If we're waiting and the child hasn't died by now, force it
+ // with a SIGKILL.
if (!exited)
result = kill(process_id, SIGKILL) == 0;
}
@@ -558,6 +561,9 @@ bool LaunchAppImpl(
} else {
// Parent process
if (wait) {
+ // While this isn't strictly disk IO, waiting for another process to
+ // finish is the sort of thing ThreadRestrictions is trying to prevent.
+ base::ThreadRestrictions::AssertIOAllowed();
pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0));
DPCHECK(ret > 0);
}
@@ -635,40 +641,45 @@ void RaiseProcessToHighPriority() {
// setpriority() or sched_getscheduler, but these all require extra rights.
}
-bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
- int status;
+TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
+ int status = 0;
const pid_t result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
if (result == -1) {
PLOG(ERROR) << "waitpid(" << handle << ")";
- if (child_exited)
- *child_exited = false;
- return false;
+ if (exit_code)
+ *exit_code = 0;
+ return TERMINATION_STATUS_NORMAL_TERMINATION;
} else if (result == 0) {
// the child hasn't exited yet.
- if (child_exited)
- *child_exited = false;
- return false;
+ if (exit_code)
+ *exit_code = 0;
+ return TERMINATION_STATUS_STILL_RUNNING;
}
- if (child_exited)
- *child_exited = true;
+ if (exit_code)
+ *exit_code = status;
if (WIFSIGNALED(status)) {
switch (WTERMSIG(status)) {
- case SIGSEGV:
- case SIGILL:
case SIGABRT:
+ case SIGBUS:
case SIGFPE:
- return true;
+ case SIGILL:
+ case SIGSEGV:
+ return TERMINATION_STATUS_PROCESS_CRASHED;
+ case SIGINT:
+ case SIGKILL:
+ case SIGTERM:
+ return TERMINATION_STATUS_PROCESS_WAS_KILLED;
default:
- return false;
+ break;
}
}
- if (WIFEXITED(status))
- return WEXITSTATUS(status) != 0;
+ if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
+ return TERMINATION_STATUS_ABNORMAL_TERMINATION;
- return false;
+ return TERMINATION_STATUS_NORMAL_TERMINATION;
}
bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
@@ -753,6 +764,9 @@ int64 TimeValToMicroseconds(const struct timeval& tv) {
static bool GetAppOutputInternal(const CommandLine& cl, char* const envp[],
std::string* output, size_t max_output,
bool do_search_path) {
+ // Doing a blocking wait for another command to finish counts as IO.
+ base::ThreadRestrictions::AssertIOAllowed();
+
int pipe_fd[2];
pid_t pid;
InjectiveMultimap fd_shuffle1, fd_shuffle2;
@@ -868,7 +882,7 @@ bool GetAppOutputRestricted(const CommandLine& cl,
return GetAppOutputInternal(cl, &empty_environ, output, max_output, false);
}
-bool WaitForProcessesToExit(const std::wstring& executable_name,
+bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
int64 wait_milliseconds,
const ProcessFilter* filter) {
bool result = false;
@@ -890,7 +904,7 @@ bool WaitForProcessesToExit(const std::wstring& executable_name,
return result;
}
-bool CleanupProcesses(const std::wstring& executable_name,
+bool CleanupProcesses(const FilePath::StringType& executable_name,
int64 wait_milliseconds,
int exit_code,
const ProcessFilter* filter) {
diff --git a/base/process_util_unittest.cc b/base/process_util_unittest.cc
index 34c444c..0eaf5d4 100644
--- a/base/process_util_unittest.cc
+++ b/base/process_util_unittest.cc
@@ -7,6 +7,7 @@
#include <limits>
#include "base/command_line.h"
+#include "base/debug_util.h"
#include "base/eintr_wrapper.h"
#include "base/file_path.h"
#include "base/logging.h"
@@ -15,6 +16,7 @@
#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
#include "base/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
@@ -27,6 +29,7 @@
#if defined(OS_POSIX)
#include <dlfcn.h>
#include <fcntl.h>
+#include <signal.h>
#include <sys/resource.h>
#include <sys/socket.h>
#endif
@@ -41,11 +44,25 @@
namespace {
#if defined(OS_WIN)
-const wchar_t* const kProcessName = L"base_unittests.exe";
+const wchar_t kProcessName[] = L"base_unittests.exe";
#else
-const wchar_t* const kProcessName = L"base_unittests";
+const wchar_t kProcessName[] = L"base_unittests";
#endif // defined(OS_WIN)
+const char kSignalFileSlow[] = "SlowChildProcess.die";
+const char kSignalFileCrash[] = "CrashingChildProcess.die";
+const char kSignalFileKill[] = "KilledChildProcess.die";
+
+#if defined(OS_WIN)
+const int kExpectedStillRunningExitCode = 0x102;
+const int kExpectedKilledExitCode = 1;
+#else
+const int kExpectedStillRunningExitCode = 0;
+#endif
+
+// The longest we'll wait for a process, in milliseconds.
+const int kMaxWaitTimeMs = TestTimeouts::action_max_timeout_ms();
+
// Sleeps until file filename is created.
void WaitToDie(const char* filename) {
FILE *fp;
@@ -62,6 +79,27 @@ void SignalChildren(const char* filename) {
fclose(fp);
}
+// Using a pipe to the child to wait for an event was considered, but
+// there were cases in the past where pipes caused problems (other
+// libraries closing the fds, child deadlocking). This is a simple
+// case, so it's not worth the risk. Using wait loops is discouraged
+// in most instances.
+base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle,
+ int* exit_code) {
+ // Now we wait until the result is something other than STILL_RUNNING.
+ base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING;
+ const int kIntervalMs = 20;
+ int waited = 0;
+ do {
+ status = base::GetTerminationStatus(handle, exit_code);
+ PlatformThread::Sleep(kIntervalMs);
+ waited += kIntervalMs;
+ } while (status == base::TERMINATION_STATUS_STILL_RUNNING &&
+ waited < kMaxWaitTimeMs);
+
+ return status;
+}
+
} // namespace
class ProcessUtilTest : public base::MultiProcessTest {
@@ -79,40 +117,140 @@ MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
TEST_F(ProcessUtilTest, SpawnChild) {
base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false);
ASSERT_NE(base::kNullProcessHandle, handle);
- EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000));
+ EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs));
base::CloseProcessHandle(handle);
}
MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
- WaitToDie("SlowChildProcess.die");
+ WaitToDie(kSignalFileSlow);
return 0;
}
TEST_F(ProcessUtilTest, KillSlowChild) {
- remove("SlowChildProcess.die");
+ remove(kSignalFileSlow);
base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false);
ASSERT_NE(base::kNullProcessHandle, handle);
- SignalChildren("SlowChildProcess.die");
- EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000));
+ SignalChildren(kSignalFileSlow);
+ EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs));
base::CloseProcessHandle(handle);
- remove("SlowChildProcess.die");
+ remove(kSignalFileSlow);
}
-TEST_F(ProcessUtilTest, DidProcessCrash) {
- remove("SlowChildProcess.die");
+TEST_F(ProcessUtilTest, GetTerminationStatusExit) {
+ remove(kSignalFileSlow);
base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false);
ASSERT_NE(base::kNullProcessHandle, handle);
- bool child_exited = true;
- EXPECT_FALSE(base::DidProcessCrash(&child_exited, handle));
- EXPECT_FALSE(child_exited);
+ int exit_code = 42;
+ EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
+ base::GetTerminationStatus(handle, &exit_code));
+ EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
+
+ SignalChildren(kSignalFileSlow);
+ exit_code = 42;
+ base::TerminationStatus status =
+ WaitForChildTermination(handle, &exit_code);
+ EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status);
+ EXPECT_EQ(0, exit_code);
+ base::CloseProcessHandle(handle);
+ remove(kSignalFileSlow);
+}
- SignalChildren("SlowChildProcess.die");
- EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000));
+#if !defined(OS_MACOSX)
+// This test is disabled on Mac, since it's flaky due to ReportCrash
+// taking a variable amount of time to parse and load the debug and
+// symbol data for this unit test's executable before firing the
+// signal handler.
+//
+// TODO(gspencer): turn this test process into a very small program
+// with no symbols (instead of using the multiprocess testing
+// framework) to reduce the ReportCrash overhead.
+
+MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
+ WaitToDie(kSignalFileCrash);
+#if defined(OS_POSIX)
+ // Have to disable to signal handler for segv so we can get a crash
+ // instead of an abnormal termination through the crash dump handler.
+ ::signal(SIGSEGV, SIG_DFL);
+#endif
+ // Make this process have a segmentation fault.
+ int* oops = NULL;
+ *oops = 0xDEAD;
+ return 1;
+}
+
+TEST_F(ProcessUtilTest, GetTerminationStatusCrash) {
+ remove(kSignalFileCrash);
+ base::ProcessHandle handle = this->SpawnChild("CrashingChildProcess",
+ false);
+ ASSERT_NE(base::kNullProcessHandle, handle);
- EXPECT_FALSE(base::DidProcessCrash(&child_exited, handle));
+ int exit_code = 42;
+ EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
+ base::GetTerminationStatus(handle, &exit_code));
+ EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
+
+ SignalChildren(kSignalFileCrash);
+ exit_code = 42;
+ base::TerminationStatus status =
+ WaitForChildTermination(handle, &exit_code);
+ EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status);
+
+#if defined(OS_WIN)
+ EXPECT_EQ(0xc0000005, exit_code);
+#elif defined(OS_POSIX)
+ int signaled = WIFSIGNALED(exit_code);
+ EXPECT_NE(0, signaled);
+ int signal = WTERMSIG(exit_code);
+ EXPECT_EQ(SIGSEGV, signal);
+#endif
+ base::CloseProcessHandle(handle);
+
+ // Reset signal handlers back to "normal".
+ base::EnableInProcessStackDumping();
+ remove(kSignalFileCrash);
+}
+#endif // !defined(OS_MACOSX)
+
+MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
+ WaitToDie(kSignalFileKill);
+#if defined(OS_WIN)
+ // Kill ourselves.
+ HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId());
+ ::TerminateProcess(handle, kExpectedKilledExitCode);
+#elif defined(OS_POSIX)
+ // Send a SIGKILL to this process, just like the OOM killer would.
+ ::kill(getpid(), SIGKILL);
+#endif
+ return 1;
+}
+
+TEST_F(ProcessUtilTest, GetTerminationStatusKill) {
+ remove(kSignalFileKill);
+ base::ProcessHandle handle = this->SpawnChild("KilledChildProcess",
+ false);
+ ASSERT_NE(base::kNullProcessHandle, handle);
+
+ int exit_code = 42;
+ EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
+ base::GetTerminationStatus(handle, &exit_code));
+ EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
+
+ SignalChildren(kSignalFileKill);
+ exit_code = 42;
+ base::TerminationStatus status =
+ WaitForChildTermination(handle, &exit_code);
+ EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
+#if defined(OS_WIN)
+ EXPECT_EQ(kExpectedKilledExitCode, exit_code);
+#elif defined(OS_POSIX)
+ int signaled = WIFSIGNALED(exit_code);
+ EXPECT_NE(0, signaled);
+ int signal = WTERMSIG(exit_code);
+ EXPECT_EQ(SIGKILL, signal);
+#endif
base::CloseProcessHandle(handle);
- remove("SlowChildProcess.die");
+ remove(kSignalFileKill);
}
// Ensure that the priority of a process is restored correctly after
diff --git a/base/process_util_win.cc b/base/process_util_win.cc
index 097888e..71f0a1a 100644
--- a/base/process_util_win.cc
+++ b/base/process_util_win.cc
@@ -30,6 +30,20 @@ namespace {
// System pagesize. This value remains constant on x86/64 architectures.
const int PAGESIZE_KB = 4;
+// Exit codes with special meanings on Windows.
+const DWORD kNormalTerminationExitCode = 0;
+const DWORD kDebuggerInactiveExitCode = 0xC0000354;
+const DWORD kKeyboardInterruptExitCode = 0xC000013A;
+const DWORD kDebuggerTerminatedExitCode = 0x40010004;
+
+// This exit code is used by the Windows task manager when it kills a
+// process. It's value is obviously not that unique, and it's
+// surprising to me that the task manager uses this value, but it
+// seems to be common practice on Windows to test for it as an
+// indication that the task manager has killed something if the
+// process goes away.
+const DWORD kProcessKilledExitCode = 1;
+
// HeapSetInformation function pointer.
typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
@@ -105,10 +119,10 @@ bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
ProcessHandle result = OpenProcess(PROCESS_DUP_HANDLE |
- PROCESS_TERMINATE |
- PROCESS_QUERY_INFORMATION |
- PROCESS_VM_READ |
- SYNCHRONIZE,
+ PROCESS_TERMINATE |
+ PROCESS_QUERY_INFORMATION |
+ PROCESS_VM_READ |
+ SYNCHRONIZE,
FALSE, pid);
if (result == INVALID_HANDLE_VALUE)
@@ -394,22 +408,33 @@ bool KillProcess(ProcessHandle process, int exit_code, bool wait) {
return result;
}
-bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
- DWORD exitcode = 0;
+TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
+ DWORD tmp_exit_code = 0;
- if (!::GetExitCodeProcess(handle, &exitcode)) {
+ if (!::GetExitCodeProcess(handle, &tmp_exit_code)) {
NOTREACHED();
- // Assume the child has exited.
- if (child_exited)
- *child_exited = true;
- return false;
+ if (exit_code) {
+ // This really is a random number. We haven't received any
+ // information about the exit code, presumably because this
+ // process doesn't have permission to get the exit code, or
+ // because of some other cause for GetExitCodeProcess to fail
+ // (MSDN docs don't give the possible failure error codes for
+ // this function, so it could be anything). But we don't want
+ // to leave exit_code uninitialized, since that could cause
+ // random interpretations of the exit code. So we assume it
+ // terminated "normally" in this case.
+ *exit_code = kNormalTerminationExitCode;
+ }
+ // Assume the child has exited normally if we can't get the exit
+ // code.
+ return TERMINATION_STATUS_NORMAL_TERMINATION;
}
- if (exitcode == STILL_ACTIVE) {
+ if (tmp_exit_code == STILL_ACTIVE) {
DWORD wait_result = WaitForSingleObject(handle, 0);
if (wait_result == WAIT_TIMEOUT) {
- if (child_exited)
- *child_exited = false;
- return false;
+ if (exit_code)
+ *exit_code = wait_result;
+ return TERMINATION_STATUS_STILL_RUNNING;
}
DCHECK_EQ(WAIT_OBJECT_0, wait_result);
@@ -417,27 +442,24 @@ bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
// Strange, the process used 0x103 (STILL_ACTIVE) as exit code.
NOTREACHED();
- return false;
+ return TERMINATION_STATUS_ABNORMAL_TERMINATION;
}
- // We're sure the child has exited.
- if (child_exited)
- *child_exited = true;
+ if (exit_code)
+ *exit_code = tmp_exit_code;
- // Warning, this is not generic code; it heavily depends on the way
- // the rest of the code kills a process.
-
- if (exitcode == PROCESS_END_NORMAL_TERMINATION ||
- exitcode == PROCESS_END_KILLED_BY_USER ||
- exitcode == PROCESS_END_PROCESS_WAS_HUNG ||
- exitcode == 0xC0000354 || // STATUS_DEBUGGER_INACTIVE.
- exitcode == 0xC000013A || // Control-C/end session.
- exitcode == 0x40010004) { // Debugger terminated process/end session.
- return false;
+ switch (tmp_exit_code) {
+ case kNormalTerminationExitCode:
+ return TERMINATION_STATUS_NORMAL_TERMINATION;
+ case kDebuggerInactiveExitCode: // STATUS_DEBUGGER_INACTIVE.
+ case kKeyboardInterruptExitCode: // Control-C/end session.
+ case kDebuggerTerminatedExitCode: // Debugger terminated process.
+ case kProcessKilledExitCode: // Task manager kill.
+ return TERMINATION_STATUS_PROCESS_WAS_KILLED;
+ default:
+ // All other exit codes indicate crashes.
+ return TERMINATION_STATUS_PROCESS_CRASHED;
}
-
- // All other exit codes indicate crashes.
- return true;
}
bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
diff --git a/base/raw_scoped_refptr_mismatch_checker.h b/base/raw_scoped_refptr_mismatch_checker.h
index d2913e7..b79cfb5 100644
--- a/base/raw_scoped_refptr_mismatch_checker.h
+++ b/base/raw_scoped_refptr_mismatch_checker.h
@@ -7,165 +7,124 @@
#pragma once
#include "base/ref_counted.h"
+#include "base/template_util.h"
#include "base/tuple.h"
+#include "build/build_config.h"
-// It is dangerous to post a task with a raw pointer argument to a function
-// that expects a scoped_refptr<>. The compiler will happily accept the
-// situation, but it will not attempt to increase the refcount until the task
-// runs. Callers expecting the argument to be refcounted up at post time are
-// in for a nasty surprise! Example: http://crbug.com/27191
+// It is dangerous to post a task with a T* argument where T is a subtype of
+// RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the
+// object may already have been deleted since it was not held with a
+// scoped_refptr. Example: http://crbug.com/27191
// The following set of traits are designed to generate a compile error
// whenever this antipattern is attempted.
-template <class A, class B>
-struct ExpectsScopedRefptrButGetsRawPtr {
+
+namespace base {
+
+// This is a base internal implementation file used by task.h and callback.h.
+// Not for public consumption, so we wrap it in namespace internal.
+namespace internal {
+
+template <typename T>
+struct NeedsScopedRefptrButGetsRawPtr {
+#if defined(OS_WIN)
+ enum {
+ value = base::false_type::value
+ };
+#else
+ enum {
+ // Human readable translation: you needed to be a scoped_refptr if you are a
+ // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase)
+ // type.
+ value = (is_pointer<T>::value &&
+ (is_convertible<T, subtle::RefCountedBase*>::value ||
+ is_convertible<T, subtle::RefCountedThreadSafeBase*>::value))
+ };
+#endif
+};
+
+template <typename Params>
+struct ParamsUseScopedRefptrCorrectly {
enum { value = 0 };
};
-template <class A, class B>
-struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> {
+template <>
+struct ParamsUseScopedRefptrCorrectly<Tuple0> {
enum { value = 1 };
};
-template <class Function, class Params>
-struct FunctionUsesScopedRefptrCorrectly {
- enum { value = 1 };
+template <typename A>
+struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > {
+ enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value };
};
-template <class A1, class A2>
-struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > {
- enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value };
+template <typename A, typename B>
+struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > {
+ enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
+ NeedsScopedRefptrButGetsRawPtr<B>::value) };
};
-template <class A1, class B1, class A2, class B2>
-struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1), Tuple2<A2, B2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) };
+template <typename A, typename B, typename C>
+struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > {
+ enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
+ NeedsScopedRefptrButGetsRawPtr<B>::value ||
+ NeedsScopedRefptrButGetsRawPtr<C>::value) };
};
-template <class A1, class B1, class C1, class A2, class B2, class C2>
-struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1),
- Tuple3<A2, B2, C2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) };
+template <typename A, typename B, typename C, typename D>
+struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D> > {
+ enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
+ NeedsScopedRefptrButGetsRawPtr<B>::value ||
+ NeedsScopedRefptrButGetsRawPtr<C>::value ||
+ NeedsScopedRefptrButGetsRawPtr<D>::value) };
};
-template <class A1, class B1, class C1, class D1,
- class A2, class B2, class C2, class D2>
-struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1),
- Tuple4<A2, B2, C2, D2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) };
+template <typename A, typename B, typename C, typename D, typename E>
+struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E> > {
+ enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
+ NeedsScopedRefptrButGetsRawPtr<B>::value ||
+ NeedsScopedRefptrButGetsRawPtr<C>::value ||
+ NeedsScopedRefptrButGetsRawPtr<D>::value ||
+ NeedsScopedRefptrButGetsRawPtr<E>::value) };
};
-template <class A1, class B1, class C1, class D1, class E1,
- class A2, class B2, class C2, class D2, class E2>
-struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1),
- Tuple5<A2, B2, C2, D2, E2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) };
+template <typename A, typename B, typename C, typename D, typename E,
+ typename F>
+struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F> > {
+ enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
+ NeedsScopedRefptrButGetsRawPtr<B>::value ||
+ NeedsScopedRefptrButGetsRawPtr<C>::value ||
+ NeedsScopedRefptrButGetsRawPtr<D>::value ||
+ NeedsScopedRefptrButGetsRawPtr<E>::value ||
+ NeedsScopedRefptrButGetsRawPtr<F>::value) };
};
-template <class A1, class B1, class C1, class D1, class E1, class F1,
- class A2, class B2, class C2, class D2, class E2, class F2>
-struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1),
- Tuple6<A2, B2, C2, D2, E2, F2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) };
+template <typename A, typename B, typename C, typename D, typename E,
+ typename F, typename G>
+struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G> > {
+ enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
+ NeedsScopedRefptrButGetsRawPtr<B>::value ||
+ NeedsScopedRefptrButGetsRawPtr<C>::value ||
+ NeedsScopedRefptrButGetsRawPtr<D>::value ||
+ NeedsScopedRefptrButGetsRawPtr<E>::value ||
+ NeedsScopedRefptrButGetsRawPtr<F>::value ||
+ NeedsScopedRefptrButGetsRawPtr<G>::value) };
};
-template <class A1, class B1, class C1, class D1, class E1, class F1, class G1,
- class A2, class B2, class C2, class D2, class E2, class F2, class G2>
-struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1, G1),
- Tuple7<A2, B2, C2, D2, E2, F2, G2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) };
+template <typename A, typename B, typename C, typename D, typename E,
+ typename F, typename G, typename H>
+struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > {
+ enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
+ NeedsScopedRefptrButGetsRawPtr<B>::value ||
+ NeedsScopedRefptrButGetsRawPtr<C>::value ||
+ NeedsScopedRefptrButGetsRawPtr<D>::value ||
+ NeedsScopedRefptrButGetsRawPtr<E>::value ||
+ NeedsScopedRefptrButGetsRawPtr<F>::value ||
+ NeedsScopedRefptrButGetsRawPtr<G>::value ||
+ NeedsScopedRefptrButGetsRawPtr<H>::value) };
};
-template <class Method, class Params>
-struct MethodUsesScopedRefptrCorrectly {
- enum { value = 1 };
-};
+} // namespace internal
-template <class T, class A1, class A2>
-struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1), Tuple1<A2> > {
- enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value };
-};
-
-template <class T, class A1, class B1, class A2, class B2>
-struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1), Tuple2<A2, B2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) };
-};
-
-template <class T, class A1, class B1, class C1,
- class A2, class B2, class C2>
-struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1),
- Tuple3<A2, B2, C2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) };
-};
-
-template <class T, class A1, class B1, class C1, class D1,
- class A2, class B2, class C2, class D2>
-struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1),
- Tuple4<A2, B2, C2, D2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) };
-};
-
-template <class T, class A1, class B1, class C1, class D1, class E1,
- class A2, class B2, class C2, class D2, class E2>
-struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1),
- Tuple5<A2, B2, C2, D2, E2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) };
-};
-
-template <class T, class A1, class B1, class C1, class D1, class E1, class F1,
- class A2, class B2, class C2, class D2, class E2, class F2>
-struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1),
- Tuple6<A2, B2, C2, D2, E2, F2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) };
-};
-
-template <class T,
- class A1, class B1, class C1, class D1, class E1, class F1, class G1,
- class A2, class B2, class C2, class D2, class E2, class F2, class G2>
-struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1, G1),
- Tuple7<A2, B2, C2, D2, E2, F2, G2> > {
- enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value ||
- ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) };
-};
+} // namespace base
#endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
diff --git a/base/scoped_handle_win.h b/base/scoped_handle_win.h
index a98114b..09bb2cb 100644
--- a/base/scoped_handle_win.h
+++ b/base/scoped_handle_win.h
@@ -4,14 +4,13 @@
// TODO(brettw) remove this file when all callers are converted to using the
// new location/namespace
-#include "base/win/scoped_handle.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/scoped_handle.h"
+#include "base/win/scoped_handle.h"
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_hglobal.h"
using base::win::ScopedBitmap;
-using base::win::ScopedGDIObject;
using base::win::ScopedHandle;
using base::win::ScopedHDC;
using base::win::ScopedHFONT;
diff --git a/base/scoped_variant_win.h b/base/scoped_variant_win.h
deleted file mode 100644
index 3d6b650..0000000
--- a/base/scoped_variant_win.h
+++ /dev/null
@@ -1,9 +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.
-
-// TODO(brettw) remove this file when all callers are converted to using the
-// new location/namespace
-#include "base/win/scoped_variant.h"
-
-using base::win::ScopedVariant;
diff --git a/base/singleton.h b/base/singleton.h
index 8435c43..e5713c4 100644
--- a/base/singleton.h
+++ b/base/singleton.h
@@ -114,7 +114,6 @@ template <typename Type> intptr_t
template <typename Type> base::subtle::Atomic32
StaticMemorySingletonTraits<Type>::dead_ = 0;
-
// The Singleton<Type, Traits, DifferentiatingType> class manages a single
// instance of Type which will be created on first use and will be destroyed at
// normal process exit). The Trait::Delete function will not be called on
@@ -124,15 +123,37 @@ template <typename Type> base::subtle::Atomic32
// singletons having the same memory allocation functions but serving a
// different purpose. This is mainly used for Locks serving different purposes.
//
-// Example usages: (none are preferred, they all result in the same code)
-// 1. FooClass* ptr = Singleton<FooClass>::get();
-// ptr->Bar();
-// 2. Singleton<FooClass>()->Bar();
-// 3. Singleton<FooClass>::get()->Bar();
+// Example usage:
+//
+// In your header:
+// #include "base/singleton.h"
+// class FooClass {
+// public:
+// static FooClass* GetInstance(); <-- See comment below on this.
+// void Bar() { ... }
+// private:
+// FooClass() { ... }
+// friend struct DefaultSingletonTraits<FooClass>;
+//
+// DISALLOW_COPY_AND_ASSIGN(FooClass);
+// };
+//
+// In your source file:
+// FooClass* FooClass::GetInstance() {
+// return Singleton<FooClass>::get();
+// }
+//
+// And to call methods on FooClass:
+// FooClass::GetInstance()->Bar();
+//
+// NOTE: The method accessing Singleton<T>::get() has to be named as GetInstance
+// and it is important that FooClass::GetInstance() is not inlined in the
+// header. This makes sure that when source files from multiple targets include
+// this header they don't end up with different copies of the inlined code
+// creating multiple copies of the singleton.
//
// Singleton<> has no non-static members and doesn't need to actually be
-// instantiated. It does no harm to instantiate it and use it as a class member
-// or at global level since it is acting as a POD type.
+// instantiated.
//
// This class is itself thread-safe. The underlying Type must of course be
// thread-safe if you want to use it concurrently. Two parameters may be tuned
@@ -152,20 +173,6 @@ template <typename Type> base::subtle::Atomic32
// shouldn't be false unless absolutely necessary. Remember that the heap where
// the object is allocated may be destroyed by the CRT anyway.
//
-// If you want to ensure that your class can only exist as a singleton, make
-// its constructors private, and make DefaultSingletonTraits<> a friend:
-//
-// #include "base/singleton.h"
-// class FooClass {
-// public:
-// void Bar() { ... }
-// private:
-// FooClass() { ... }
-// friend struct DefaultSingletonTraits<FooClass>;
-//
-// DISALLOW_COPY_AND_ASSIGN(FooClass);
-// };
-//
// Caveats:
// (a) Every call to get(), operator->() and operator*() incurs some overhead
// (16ns on my P4/2.8GHz) to check whether the object has already been
@@ -179,7 +186,11 @@ template <typename Type,
typename Traits = DefaultSingletonTraits<Type>,
typename DifferentiatingType = Type>
class Singleton {
- public:
+ private:
+ // Classes using the Singleton<T> pattern should declare a GetInstance()
+ // method and call Singleton::get() from within that.
+ friend Type* Type::GetInstance();
+
// This class is safe to be constructed and copy-constructed since it has no
// member.
@@ -240,16 +251,6 @@ class Singleton {
return reinterpret_cast<Type*>(value);
}
- // Shortcuts.
- Type& operator*() {
- return *get();
- }
-
- Type* operator->() {
- return get();
- }
-
- private:
// Adapter function for use with AtExit(). This should be called single
// threaded, so don't use atomic operations.
// Calling OnExit while singleton is in use by other threads is a mistake.
diff --git a/base/singleton_unittest.cc b/base/singleton_unittest.cc
index acb1247..3d7e7e6 100644
--- a/base/singleton_unittest.cc
+++ b/base/singleton_unittest.cc
@@ -12,87 +12,131 @@ namespace {
COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
-template<typename Type>
-struct LockTrait : public DefaultSingletonTraits<Type> {
-};
+typedef void (*CallbackFunc)();
-struct Init5Trait : public DefaultSingletonTraits<int> {
- static int* New() {
- return new int(5);
+class IntSingleton {
+ public:
+ static IntSingleton* GetInstance() {
+ return Singleton<IntSingleton>::get();
}
+
+ int value_;
};
-typedef void (*CallbackFunc)();
+class Init5Singleton {
+ public:
+ struct Trait;
-struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> {
- static void Delete(CallbackFunc* p) {
- if (*p)
- (*p)();
- DefaultSingletonTraits<CallbackFunc>::Delete(p);
+ static Init5Singleton* GetInstance() {
+ return Singleton<Init5Singleton, Trait>::get();
}
+
+ int value_;
};
-struct StaticCallbackTrait : public StaticMemorySingletonTraits<CallbackFunc> {
- static void Delete(CallbackFunc* p) {
- if (*p)
- (*p)();
- StaticMemorySingletonTraits<CallbackFunc>::Delete(p);
+struct Init5Singleton::Trait : public DefaultSingletonTraits<Init5Singleton> {
+ static Init5Singleton* New() {
+ Init5Singleton* instance = new Init5Singleton();
+ instance->value_ = 5;
+ return instance;
}
};
+int* SingletonInt() {
+ return &IntSingleton::GetInstance()->value_;
+}
+
+int* SingletonInt5() {
+ return &Init5Singleton::GetInstance()->value_;
+}
-struct NoLeakTrait : public CallbackTrait {
+template <typename Type>
+struct CallbackTrait : public DefaultSingletonTraits<Type> {
+ static void Delete(Type* instance) {
+ if (instance->callback_)
+ (instance->callback_)();
+ DefaultSingletonTraits<Type>::Delete(instance);
+ }
};
-struct LeakTrait : public CallbackTrait {
- static const bool kRegisterAtExit = false;
+class CallbackSingleton {
+ public:
+ CallbackSingleton() : callback_(NULL) { }
+ CallbackFunc callback_;
};
-int* SingletonInt1() {
- return Singleton<int>::get();
-}
+class CallbackSingletonWithNoLeakTrait : public CallbackSingleton {
+ public:
+ struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { };
-int* SingletonInt2() {
- // Force to use a different singleton than SingletonInt1.
- return Singleton<int, DefaultSingletonTraits<int> >::get();
-}
+ CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
-class DummyDifferentiatingClass {
+ static CallbackSingletonWithNoLeakTrait* GetInstance() {
+ return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get();
+ }
};
-int* SingletonInt3() {
- // Force to use a different singleton than SingletonInt1 and SingletonInt2.
- // Note that any type can be used; int, float, std::wstring...
- return Singleton<int, DefaultSingletonTraits<int>,
- DummyDifferentiatingClass>::get();
-}
+class CallbackSingletonWithLeakTrait : public CallbackSingleton {
+ public:
+ struct Trait : public CallbackTrait<CallbackSingletonWithLeakTrait> {
+ static const bool kRegisterAtExit = false;
+ };
-int* SingletonInt4() {
- return Singleton<int, LockTrait<int> >::get();
-}
+ CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
+
+ static CallbackSingletonWithLeakTrait* GetInstance() {
+ return Singleton<CallbackSingletonWithLeakTrait, Trait>::get();
+ }
+};
+
+class CallbackSingletonWithStaticTrait : public CallbackSingleton {
+ public:
+ struct Trait;
+
+ CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
+
+ static CallbackSingletonWithStaticTrait* GetInstance() {
+ return Singleton<CallbackSingletonWithStaticTrait, Trait>::get();
+ }
+};
+
+struct CallbackSingletonWithStaticTrait::Trait
+ : public StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait> {
+ static void Delete(CallbackSingletonWithStaticTrait* instance) {
+ if (instance->callback_)
+ (instance->callback_)();
+ StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait>::Delete(
+ instance);
+ }
+};
-int* SingletonInt5() {
- return Singleton<int, Init5Trait>::get();
-}
void SingletonNoLeak(CallbackFunc CallOnQuit) {
- *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit;
+ CallbackSingletonWithNoLeakTrait::GetInstance()->callback_ = CallOnQuit;
}
void SingletonLeak(CallbackFunc CallOnQuit) {
- *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit;
+ CallbackSingletonWithLeakTrait::GetInstance()->callback_ = CallOnQuit;
}
CallbackFunc* GetLeakySingleton() {
- return Singleton<CallbackFunc, LeakTrait>::get();
+ return &CallbackSingletonWithLeakTrait::GetInstance()->callback_;
+}
+
+void DeleteLeakySingleton() {
+ DefaultSingletonTraits<CallbackSingletonWithLeakTrait>::Delete(
+ CallbackSingletonWithLeakTrait::GetInstance());
}
void SingletonStatic(CallbackFunc CallOnQuit) {
- *Singleton<CallbackFunc, StaticCallbackTrait>::get() = CallOnQuit;
+ CallbackSingletonWithStaticTrait::GetInstance()->callback_ = CallOnQuit;
}
CallbackFunc* GetStaticSingleton() {
- return Singleton<CallbackFunc, StaticCallbackTrait>::get();
+ return &CallbackSingletonWithStaticTrait::GetInstance()->callback_;
+}
+
+void ResurrectStaticSingleton() {
}
} // namespace
@@ -149,10 +193,7 @@ bool SingletonTest::leaky_called_ = false;
bool SingletonTest::static_called_ = false;
TEST_F(SingletonTest, Basic) {
- int* singleton_int_1;
- int* singleton_int_2;
- int* singleton_int_3;
- int* singleton_int_4;
+ int* singleton_int;
int* singleton_int_5;
CallbackFunc* leaky_singleton;
CallbackFunc* static_singleton;
@@ -160,49 +201,20 @@ TEST_F(SingletonTest, Basic) {
{
base::ShadowingAtExitManager sem;
{
- singleton_int_1 = SingletonInt1();
+ singleton_int = SingletonInt();
}
// Ensure POD type initialization.
- EXPECT_EQ(*singleton_int_1, 0);
- *singleton_int_1 = 1;
-
- EXPECT_EQ(singleton_int_1, SingletonInt1());
- EXPECT_EQ(*singleton_int_1, 1);
-
- {
- singleton_int_2 = SingletonInt2();
- }
- // Same instance that 1.
- EXPECT_EQ(*singleton_int_2, 1);
- EXPECT_EQ(singleton_int_1, singleton_int_2);
+ EXPECT_EQ(*singleton_int, 0);
+ *singleton_int = 1;
- {
- singleton_int_3 = SingletonInt3();
- }
- // Different instance than 1 and 2.
- EXPECT_EQ(*singleton_int_3, 0);
- EXPECT_NE(singleton_int_1, singleton_int_3);
- *singleton_int_3 = 3;
- EXPECT_EQ(*singleton_int_1, 1);
- EXPECT_EQ(*singleton_int_2, 1);
-
- {
- singleton_int_4 = SingletonInt4();
- }
- // Use a lock for creation. Not really tested at length.
- EXPECT_EQ(*singleton_int_4, 0);
- *singleton_int_4 = 4;
- EXPECT_NE(singleton_int_1, singleton_int_4);
- EXPECT_NE(singleton_int_3, singleton_int_4);
+ EXPECT_EQ(singleton_int, SingletonInt());
+ EXPECT_EQ(*singleton_int, 1);
{
singleton_int_5 = SingletonInt5();
}
// Is default initialized to 5.
EXPECT_EQ(*singleton_int_5, 5);
- EXPECT_NE(singleton_int_1, singleton_int_5);
- EXPECT_NE(singleton_int_3, singleton_int_5);
- EXPECT_NE(singleton_int_4, singleton_int_5);
SingletonNoLeak(&CallbackNoLeak);
SingletonLeak(&CallbackLeak);
@@ -216,7 +228,7 @@ TEST_F(SingletonTest, Basic) {
VerifiesCallbacks();
// Delete the leaky singleton. It is interesting to note that Purify does
// *not* detect the leak when this call is commented out. :(
- DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton);
+ DeleteLeakySingleton();
// The static singleton can't be acquired post-atexit.
EXPECT_EQ(NULL, GetStaticSingleton());
@@ -225,8 +237,8 @@ TEST_F(SingletonTest, Basic) {
base::ShadowingAtExitManager sem;
// Verifiy that the variables were reset.
{
- singleton_int_1 = SingletonInt1();
- EXPECT_EQ(*singleton_int_1, 0);
+ singleton_int = SingletonInt();
+ EXPECT_EQ(*singleton_int, 0);
}
{
singleton_int_5 = SingletonInt5();
@@ -235,7 +247,7 @@ TEST_F(SingletonTest, Basic) {
{
// Resurrect the static singleton, and assert that it
// still points to the same (static) memory.
- StaticMemorySingletonTraits<CallbackFunc>::Resurrect();
+ CallbackSingletonWithStaticTrait::Trait::Resurrect();
EXPECT_EQ(GetStaticSingleton(), static_singleton);
}
}
diff --git a/base/string_util.cc b/base/string_util.cc
index 1c97487..0e0f17b 100644
--- a/base/string_util.cc
+++ b/base/string_util.cc
@@ -38,6 +38,10 @@ struct EmptyStrings {
const std::string s;
const std::wstring ws;
const string16 s16;
+
+ static EmptyStrings* GetInstance() {
+ return Singleton<EmptyStrings>::get();
+ }
};
// Used by ReplaceStringPlaceholders to track the position in the string of
@@ -102,15 +106,15 @@ bool IsWprintfFormatPortable(const wchar_t* format) {
const std::string& EmptyString() {
- return Singleton<EmptyStrings>::get()->s;
+ return EmptyStrings::GetInstance()->s;
}
const std::wstring& EmptyWString() {
- return Singleton<EmptyStrings>::get()->ws;
+ return EmptyStrings::GetInstance()->ws;
}
const string16& EmptyString16() {
- return Singleton<EmptyStrings>::get()->s16;
+ return EmptyStrings::GetInstance()->s16;
}
#define WHITESPACE_UNICODE \
@@ -1094,40 +1098,3 @@ size_t base::strlcpy(char* dst, const char* src, size_t dst_size) {
size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) {
return lcpyT<wchar_t>(dst, src, dst_size);
}
-
-bool ElideString(const std::wstring& input, int max_len, std::wstring* output) {
- DCHECK(max_len >= 0);
- if (static_cast<int>(input.length()) <= max_len) {
- output->assign(input);
- return false;
- }
-
- switch (max_len) {
- case 0:
- output->clear();
- break;
- case 1:
- output->assign(input.substr(0, 1));
- break;
- case 2:
- output->assign(input.substr(0, 2));
- break;
- case 3:
- output->assign(input.substr(0, 1) + L"." +
- input.substr(input.length() - 1));
- break;
- case 4:
- output->assign(input.substr(0, 1) + L".." +
- input.substr(input.length() - 1));
- break;
- default: {
- int rstr_len = (max_len - 3) / 2;
- int lstr_len = rstr_len + ((max_len - 3) % 2);
- output->assign(input.substr(0, lstr_len) + L"..." +
- input.substr(input.length() - rstr_len));
- break;
- }
- }
-
- return true;
-}
diff --git a/base/string_util.h b/base/string_util.h
index 498ccc5..f65652c 100644
--- a/base/string_util.h
+++ b/base/string_util.h
@@ -523,14 +523,6 @@ string16 ReplaceStringPlaceholders(const string16& format_string,
const string16& a,
size_t* offset);
-// If the size of |input| is more than |max_len|, this function returns true and
-// |input| is shortened into |output| by removing chars in the middle (they are
-// replaced with up to 3 dots, as size permits).
-// Ex: ElideString(L"Hello", 10, &str) puts Hello in str and returns false.
-// ElideString(L"Hello my name is Tom", 10, &str) puts "Hell...Tom" in str and
-// returns true.
-bool ElideString(const std::wstring& input, int max_len, std::wstring* output);
-
// Returns true if the string passed in matches the pattern. The pattern
// string can contain wildcards like * and ?
// The backslash character (\) is an escape character for * and ?
diff --git a/base/string_util_unittest.cc b/base/string_util_unittest.cc
index b7639bb..cd45642 100644
--- a/base/string_util_unittest.cc
+++ b/base/string_util_unittest.cc
@@ -1056,33 +1056,6 @@ TEST(StringUtilTest, WprintfFormatPortabilityTest) {
}
}
-TEST(StringUtilTest, ElideString) {
- struct TestData {
- const wchar_t* input;
- int max_len;
- bool result;
- const wchar_t* output;
- } cases[] = {
- { L"Hello", 0, true, L"" },
- { L"", 0, false, L"" },
- { L"Hello, my name is Tom", 1, true, L"H" },
- { L"Hello, my name is Tom", 2, true, L"He" },
- { L"Hello, my name is Tom", 3, true, L"H.m" },
- { L"Hello, my name is Tom", 4, true, L"H..m" },
- { L"Hello, my name is Tom", 5, true, L"H...m" },
- { L"Hello, my name is Tom", 6, true, L"He...m" },
- { L"Hello, my name is Tom", 7, true, L"He...om" },
- { L"Hello, my name is Tom", 10, true, L"Hell...Tom" },
- { L"Hello, my name is Tom", 100, false, L"Hello, my name is Tom" }
- };
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
- std::wstring output;
- EXPECT_EQ(cases[i].result,
- ElideString(cases[i].input, cases[i].max_len, &output));
- EXPECT_TRUE(output == cases[i].output);
- }
-}
-
TEST(StringUtilTest, RemoveChars) {
const char* kRemoveChars = "-/+*";
std::string input = "A-+bc/d!*";
diff --git a/base/stringprintf.h b/base/stringprintf.h
index f3ca6e7..9170ddd 100644
--- a/base/stringprintf.h
+++ b/base/stringprintf.h
@@ -49,6 +49,5 @@ void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap)
//
// TODO(brettw) remove these when calling code is converted.
using base::StringPrintf;
-using base::StringAppendV;
#endif // BASE_STRINGPRINTF_H_
diff --git a/base/task.h b/base/task.h
index b21ccd8..e6e0d2d 100644
--- a/base/task.h
+++ b/base/task.h
@@ -149,8 +149,9 @@ class ScopedRunnableMethodFactory {
: obj_(obj),
meth_(meth),
params_(params) {
- COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
- badscopedrunnablemethodparams);
+ COMPILE_ASSERT(
+ (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
+ badscopedrunnablemethodparams);
}
virtual void Run() {
@@ -317,8 +318,9 @@ class RunnableMethod : public CancelableTask {
RunnableMethod(T* obj, Method meth, const Params& params)
: obj_(obj), meth_(meth), params_(params) {
traits_.RetainCallee(obj_);
- COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
- badrunnablemethodparams);
+ COMPILE_ASSERT(
+ (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
+ badrunnablemethodparams);
}
~RunnableMethod() {
@@ -336,10 +338,10 @@ class RunnableMethod : public CancelableTask {
private:
void ReleaseCallee() {
- if (obj_) {
- traits_.ReleaseCallee(obj_);
- obj_ = NULL;
- }
+ T* obj = obj_;
+ obj_ = NULL;
+ if (obj)
+ traits_.ReleaseCallee(obj);
}
T* obj_;
@@ -429,8 +431,9 @@ class RunnableFunction : public CancelableTask {
public:
RunnableFunction(Function function, const Params& params)
: function_(function), params_(params) {
- COMPILE_ASSERT((FunctionUsesScopedRefptrCorrectly<Function, Params>::value),
- badrunnablefunctionparams);
+ COMPILE_ASSERT(
+ (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
+ badrunnablefunctionparams);
}
~RunnableFunction() {
diff --git a/base/task_unittest.cc b/base/task_unittest.cc
new file mode 100644
index 0000000..cc975e0
--- /dev/null
+++ b/base/task_unittest.cc
@@ -0,0 +1,52 @@
+// 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/ref_counted.h"
+#include "base/task.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class CancelInDestructor : public base::RefCounted<CancelInDestructor> {
+ public:
+ CancelInDestructor() : cancelable_task_(NULL) {}
+
+ void Start() {
+ if (cancelable_task_) {
+ ADD_FAILURE();
+ return;
+ }
+ AddRef();
+ cancelable_task_ = NewRunnableMethod(
+ this, &CancelInDestructor::NeverIssuedCallback);
+ Release();
+ }
+
+ CancelableTask* cancelable_task() {
+ return cancelable_task_;
+ }
+
+ private:
+ friend class base::RefCounted<CancelInDestructor>;
+
+ ~CancelInDestructor() {
+ if (cancelable_task_)
+ cancelable_task_->Cancel();
+ }
+
+ void NeverIssuedCallback() { NOTREACHED(); }
+
+ CancelableTask* cancelable_task_;
+};
+
+TEST(TaskTest, TestCancelInDestructor) {
+ // Intentionally not using a scoped_refptr for cancel_in_destructor.
+ CancelInDestructor* cancel_in_destructor = new CancelInDestructor();
+ cancel_in_destructor->Start();
+ CancelableTask* cancelable_task = cancel_in_destructor->cancelable_task();
+ ASSERT_TRUE(cancelable_task);
+ delete cancelable_task;
+}
+
+} // namespace
diff --git a/base/template_util.h b/base/template_util.h
index 2cfe04c..27bdb73 100644
--- a/base/template_util.h
+++ b/base/template_util.h
@@ -6,6 +6,8 @@
#define BASE_TEMPLATE_UTIL_H_
#pragma once
+#include "build/build_config.h"
+
namespace base {
// template definitions from tr1
@@ -25,6 +27,51 @@ typedef integral_constant<bool, false> false_type;
template <class T> struct is_pointer : false_type {};
template <class T> struct is_pointer<T*> : true_type {};
+namespace internal {
+
+// Types small_ and big_ are guaranteed such that sizeof(small_) <
+// sizeof(big_)
+typedef char small_;
+
+struct big_ {
+ small_ dummy[2];
+};
+
+#if !defined(OS_WIN)
+
+// This class is an implementation detail for is_convertible, and you
+// don't need to know how it works to use is_convertible. For those
+// who care: we declare two different functions, one whose argument is
+// of type To and one with a variadic argument list. We give them
+// return types of different size, so we can use sizeof to trick the
+// compiler into telling us which function it would have chosen if we
+// had called it with an argument of type From. See Alexandrescu's
+// _Modern C++ Design_ for more details on this sort of trick.
+
+template <typename From, typename To>
+struct ConvertHelper {
+ static small_ Test(To);
+ static big_ Test(...);
+ static From Create();
+};
+
+#endif // !defined(OS_WIN)
+
+} // namespace internal
+
+#if !defined(OS_WIN)
+
+// Inherits from true_type if From is convertible to To, false_type otherwise.
+template <typename From, typename To>
+struct is_convertible
+ : integral_constant<bool,
+ sizeof(internal::ConvertHelper<From, To>::Test(
+ internal::ConvertHelper<From, To>::Create()))
+ == sizeof(internal::small_)> {
+};
+
+#endif // !defined(OS_WIN)
+
} // namespace base
#endif // BASE_TEMPLATE_UTIL_H_
diff --git a/base/test/mock_chrome_application_mac.h b/base/test/mock_chrome_application_mac.h
new file mode 100644
index 0000000..e7e2c67
--- /dev/null
+++ b/base/test/mock_chrome_application_mac.h
@@ -0,0 +1,28 @@
+// 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.
+
+#ifndef BASE_TEST_MOCK_CHROME_APPLICATION_MAC_H_
+#define BASE_TEST_MOCK_CHROME_APPLICATION_MAC_H_
+#pragma once
+
+#if defined(__OBJC__)
+
+#import <AppKit/AppKit.h>
+
+#include "base/message_pump_mac.h"
+
+// A mock implementation of CrAppProtocol that claims that -sendEvent: is never
+// on the stack. This can be used in tests that need an NSApplication and use a
+// runloop, but don't run nested message loops.
+@interface MockCrApp : NSApplication<CrAppProtocol>
+@end
+
+#endif
+
+// To be used to instantiate MockCrApp from C++ code.
+namespace mock_cr_app {
+void RegisterMockCrApp();
+} // namespace mock_cr_app
+
+#endif // BASE_TEST_MOCK_CHROME_APPLICATION_MAC_H_
diff --git a/base/test/mock_chrome_application_mac.mm b/base/test/mock_chrome_application_mac.mm
new file mode 100644
index 0000000..f7010c4
--- /dev/null
+++ b/base/test/mock_chrome_application_mac.mm
@@ -0,0 +1,19 @@
+// 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/test/mock_chrome_application_mac.h"
+
+@implementation MockCrApp
+- (BOOL)isHandlingSendEvent {
+ return NO;
+}
+@end
+
+namespace mock_cr_app {
+
+void RegisterMockCrApp() {
+ [MockCrApp sharedApplication];
+}
+
+} // namespace mock_cr_app
diff --git a/base/test/test_switches.cc b/base/test/test_switches.cc
index 1dfd63f..991f4f3 100644
--- a/base/test/test_switches.cc
+++ b/base/test/test_switches.cc
@@ -10,6 +10,7 @@ const char switches::kLiveOperationTimeout[] = "live-operation-timeout";
// Time (in milliseconds) that the tests should wait before timing out.
// TODO(phajdan.jr): Clean up the switch names.
const char switches::kTestLargeTimeout[] = "test-large-timeout";
+const char switches::kTestTinyTimeout[] = "test-tiny-timeout";
const char switches::kUiTestActionTimeout[] = "ui-test-action-timeout";
const char switches::kUiTestActionMaxTimeout[] = "ui-test-action-max-timeout";
const char switches::kUiTestCommandExecutionTimeout[] = "ui-test-timeout";
diff --git a/base/test/test_switches.h b/base/test/test_switches.h
index 2194596..44ebd23 100644
--- a/base/test/test_switches.h
+++ b/base/test/test_switches.h
@@ -11,6 +11,7 @@ namespace switches {
// alongside the definition of their values in the .cc file.
extern const char kLiveOperationTimeout[];
extern const char kTestLargeTimeout[];
+extern const char kTestTinyTimeout[];
extern const char kUiTestActionTimeout[];
extern const char kUiTestActionMaxTimeout[];
extern const char kUiTestCommandExecutionTimeout[];
diff --git a/base/test/test_timeouts.cc b/base/test/test_timeouts.cc
index 7ee1b70..046f320 100644
--- a/base/test/test_timeouts.cc
+++ b/base/test/test_timeouts.cc
@@ -42,6 +42,7 @@ bool TestTimeouts::initialized_ = false;
// The timeout values should increase in the order they appear in this block.
// static
+int TestTimeouts::tiny_timeout_ms_ = 100;
int TestTimeouts::action_timeout_ms_ = 2000;
int TestTimeouts::action_max_timeout_ms_ = 15000;
int TestTimeouts::large_test_timeout_ms_ = 3 * 60 * 1000;
@@ -66,7 +67,9 @@ void TestTimeouts::Initialize() {
// Note that these timeouts MUST be initialized in the correct order as
// per the CHECKS below.
- InitializeTimeout(switches::kUiTestActionTimeout, &action_timeout_ms_);
+ InitializeTimeout(switches::kTestTinyTimeout, &tiny_timeout_ms_);
+ InitializeTimeout(switches::kUiTestActionTimeout, tiny_timeout_ms_,
+ &action_timeout_ms_);
InitializeTimeout(switches::kUiTestActionMaxTimeout, action_timeout_ms_,
&action_max_timeout_ms_);
InitializeTimeout(switches::kTestLargeTimeout, action_max_timeout_ms_,
@@ -75,6 +78,7 @@ void TestTimeouts::Initialize() {
&huge_test_timeout_ms_);
// The timeout values should be increasing in the right order.
+ CHECK(tiny_timeout_ms_ <= action_timeout_ms_);
CHECK(action_timeout_ms_ <= action_max_timeout_ms_);
CHECK(action_max_timeout_ms_ <= large_test_timeout_ms_);
CHECK(large_test_timeout_ms_ <= huge_test_timeout_ms_);
diff --git a/base/test/test_timeouts.h b/base/test/test_timeouts.h
index d49ca2c..f4cb1ff 100644
--- a/base/test/test_timeouts.h
+++ b/base/test/test_timeouts.h
@@ -15,6 +15,9 @@ class TestTimeouts {
// by the test suite.
static void Initialize();
+ // Timeout for actions that are expected to finish "almost instantly".
+ static int tiny_timeout_ms() { return tiny_timeout_ms_; }
+
// Timeout to wait for something to happen. If you are not sure
// which timeout to use, this is the one you want.
static int action_timeout_ms() { return action_timeout_ms_; }
@@ -52,6 +55,7 @@ class TestTimeouts {
private:
static bool initialized_;
+ static int tiny_timeout_ms_;
static int action_timeout_ms_;
static int action_max_timeout_ms_;
static int large_test_timeout_ms_;
diff --git a/base/third_party/nspr/prcpucfg.h b/base/third_party/nspr/prcpucfg.h
index 8651edd..95c2c0a 100644
--- a/base/third_party/nspr/prcpucfg.h
+++ b/base/third_party/nspr/prcpucfg.h
@@ -34,7 +34,11 @@
#include "base/third_party/nspr/prcpucfg_win.h"
#elif defined(__APPLE__)
#include "base/third_party/nspr/prcpucfg_mac.h"
+<<<<<<< HEAD
#elif defined(__linux__) || defined(ANDROID)
+=======
+#elif defined(__linux__) || defined(__native_client__)
+>>>>>>> chromium.org at r10.0.621.0
#include "base/third_party/nspr/prcpucfg_linux.h"
#elif defined(__FreeBSD__)
#include "base/third_party/nspr/prcpucfg_freebsd.h"
diff --git a/base/time_win.cc b/base/time_win.cc
index 5d3ecd6..ca3aef1 100644
--- a/base/time_win.cc
+++ b/base/time_win.cc
@@ -310,16 +310,8 @@ TimeDelta RolloverProtectedNow() {
// retrieve and more reliable.
class HighResNowSingleton {
public:
- HighResNowSingleton()
- : ticks_per_microsecond_(0.0),
- skew_(0) {
- InitializeClock();
-
- // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
- // unreliable. Fallback to low-res clock.
- base::CPU cpu;
- if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15)
- DisableHighResClock();
+ static HighResNowSingleton* GetInstance() {
+ return Singleton<HighResNowSingleton>::get();
}
bool IsUsingHighResClock() {
@@ -346,6 +338,18 @@ class HighResNowSingleton {
}
private:
+ HighResNowSingleton()
+ : ticks_per_microsecond_(0.0),
+ skew_(0) {
+ InitializeClock();
+
+ // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
+ // unreliable. Fallback to low-res clock.
+ base::CPU cpu;
+ if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15)
+ DisableHighResClock();
+ }
+
// Synchronize the QPC clock with GetSystemTimeAsFileTime.
void InitializeClock() {
LARGE_INTEGER ticks_per_sec = {0};
@@ -374,7 +378,7 @@ class HighResNowSingleton {
float ticks_per_microsecond_; // 0 indicates QPF failed and we're broken.
int64 skew_; // Skew between lo-res and hi-res clocks (for debugging).
- DISALLOW_COPY_AND_ASSIGN(HighResNowSingleton);
+ friend struct DefaultSingletonTraits<HighResNowSingleton>;
};
} // namespace
@@ -394,15 +398,15 @@ TimeTicks TimeTicks::Now() {
// static
TimeTicks TimeTicks::HighResNow() {
- return TimeTicks() + Singleton<HighResNowSingleton>::get()->Now();
+ return TimeTicks() + HighResNowSingleton::GetInstance()->Now();
}
// static
int64 TimeTicks::GetQPCDriftMicroseconds() {
- return Singleton<HighResNowSingleton>::get()->GetQPCDriftMicroseconds();
+ return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds();
}
// static
bool TimeTicks::IsHighResClockWorking() {
- return Singleton<HighResNowSingleton>::get()->IsUsingHighResClock();
+ return HighResNowSingleton::GetInstance()->IsUsingHighResClock();
} \ No newline at end of file
diff --git a/base/tuple.h b/base/tuple.h
index bfe6562..6b0d336 100644
--- a/base/tuple.h
+++ b/base/tuple.h
@@ -30,6 +30,10 @@
#define BASE_TUPLE_H__
#pragma once
+#if defined(OS_CHROMEOS)
+// To troubleshoot crosbug.com/7327.
+#include "base/logging.h"
+#endif
// Traits ----------------------------------------------------------------------
//
// A simple traits class for tuple arguments.
@@ -545,7 +549,7 @@ inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) {
template <class ObjT, class Method, class A>
inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1<A>& arg) {
-#if defined(OS_CHROMEOS) && defined(CHECK)
+#if defined(OS_CHROMEOS)
// To troubleshoot crosbug.com/7327.
CHECK(obj);
CHECK(&arg);
diff --git a/base/unix_domain_socket_posix.cc b/base/unix_domain_socket_posix.cc
deleted file mode 100644
index 73fa260..0000000
--- a/base/unix_domain_socket_posix.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2009 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/unix_domain_socket_posix.h"
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-
-#include "base/eintr_wrapper.h"
-#include "base/logging.h"
-#include "base/pickle.h"
-
-namespace base {
-
-bool SendMsg(int fd, const void* buf, size_t length,
- const std::vector<int>& fds) {
- struct msghdr msg;
- memset(&msg, 0, sizeof(msg));
- struct iovec iov = {const_cast<void*>(buf), length};
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- char* control_buffer = NULL;
- if (fds.size()) {
- const unsigned control_len = CMSG_SPACE(sizeof(int) * fds.size());
- control_buffer = new char[control_len];
-
- struct cmsghdr *cmsg;
- msg.msg_control = control_buffer;
- msg.msg_controllen = control_len;
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds.size());
- memcpy(CMSG_DATA(cmsg), &fds[0], sizeof(int) * fds.size());
- msg.msg_controllen = cmsg->cmsg_len;
- }
-
- const ssize_t r = HANDLE_EINTR(sendmsg(fd, &msg, 0));
- const bool ret = static_cast<ssize_t>(length) == r;
- delete[] control_buffer;
- return ret;
-}
-
-ssize_t RecvMsg(int fd, void* buf, size_t length, std::vector<int>* fds) {
- static const unsigned kMaxDescriptors = 16;
-
- fds->clear();
-
- struct msghdr msg;
- memset(&msg, 0, sizeof(msg));
- struct iovec iov = {buf, length};
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- char control_buffer[CMSG_SPACE(sizeof(int) * kMaxDescriptors)];
- msg.msg_control = control_buffer;
- msg.msg_controllen = sizeof(control_buffer);
-
- const ssize_t r = HANDLE_EINTR(recvmsg(fd, &msg, 0));
- if (r == -1)
- return -1;
-
- int* wire_fds = NULL;
- unsigned wire_fds_len = 0;
-
- if (msg.msg_controllen > 0) {
- struct cmsghdr* cmsg;
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
- DCHECK(payload_len % sizeof(int) == 0);
- wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
- wire_fds_len = payload_len / sizeof(int);
- break;
- }
- }
- }
-
- if (msg.msg_flags & MSG_TRUNC || msg.msg_flags & MSG_CTRUNC) {
- for (unsigned i = 0; i < wire_fds_len; ++i)
- close(wire_fds[i]);
- errno = EMSGSIZE;
- return -1;
- }
-
- fds->resize(wire_fds_len);
- memcpy(&(*fds)[0], wire_fds, sizeof(int) * wire_fds_len);
-
- return r;
-}
-
-ssize_t SendRecvMsg(int fd, uint8_t* reply, unsigned max_reply_len, int* result_fd,
- const Pickle& request) {
- int fds[2];
-
- // This socketpair is only used for the IPC and is cleaned up before
- // returning.
- if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == -1)
- return false;
-
- std::vector<int> fd_vector;
- fd_vector.push_back(fds[1]);
- if (!SendMsg(fd, request.data(), request.size(), fd_vector)) {
- close(fds[0]);
- close(fds[1]);
- return -1;
- }
- close(fds[1]);
-
- fd_vector.clear();
- const ssize_t reply_len = RecvMsg(fds[0], reply, max_reply_len, &fd_vector);
- close(fds[0]);
- if (reply_len == -1)
- return -1;
-
- if ((fd_vector.size() > 0 && result_fd == NULL) || fd_vector.size() > 1) {
- for (std::vector<int>::const_iterator
- i = fd_vector.begin(); i != fd_vector.end(); ++i) {
- close(*i);
- }
-
- NOTREACHED();
-
- return -1;
- }
-
- if (result_fd) {
- if (fd_vector.size() == 0) {
- *result_fd = -1;
- } else {
- *result_fd = fd_vector[0];
- }
- }
-
- return reply_len;
-}
-
-} // namespace base
diff --git a/base/unix_domain_socket_posix.h b/base/unix_domain_socket_posix.h
deleted file mode 100644
index 51c821b..0000000
--- a/base/unix_domain_socket_posix.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2009 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_UNIX_DOMAIN_SOCKET_POSIX_H_
-#define BASE_UNIX_DOMAIN_SOCKET_POSIX_H_
-#pragma once
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <vector>
-
-class Pickle;
-
-namespace base {
-
-// Use sendmsg to write the given msg and include a vector
-// of file descriptors. Returns true iff successful.
-bool SendMsg(int fd, const void* msg, size_t length,
- const std::vector<int>& fds);
-// Use recvmsg to read a message and an array of file descriptors. Returns
-// -1 on failure. Note: will read, at most, 16 descriptors.
-ssize_t RecvMsg(int fd, void* msg, size_t length, std::vector<int>* fds);
-// Perform a sendmsg/recvmsg pair.
-// 1. This process creates a UNIX DGRAM socketpair.
-// 2. This proces writes a request to |fd| with an SCM_RIGHTS control message
-// containing on end of the fresh socket pair.
-// 3. This process blocks reading from the other end of the fresh socketpair.
-// 4. The target process receives the request, processes it and writes the
-// reply to the end of the socketpair contained in the request.
-// 5. This process wakes up and continues.
-//
-// fd: descriptor to send the request on
-// reply: buffer for the reply
-// reply_len: size of |reply|
-// result_fd: (may be NULL) the file descriptor returned in the reply (if any)
-// request: the bytes to send in the request
-ssize_t SendRecvMsg(int fd, uint8_t* reply, unsigned reply_len, int* result_fd,
- const Pickle& request);
-
-} // namespace base
-
-#endif // BASE_UNIX_DOMAIN_SOCKET_POSIX_H_
diff --git a/base/values.cc b/base/values.cc
index cd0f6a8..4553e68 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -119,6 +119,10 @@ bool Value::GetAsString(string16* out_value) const {
return false;
}
+bool Value::GetAsList(ListValue** out_value) {
+ return false;
+}
+
Value* Value::DeepCopy() const {
// This method should only be getting called for null Values--all subclasses
// need to provide their own implementation;.
@@ -133,6 +137,13 @@ bool Value::Equals(const Value* other) const {
return other->IsType(TYPE_NULL);
}
+// static
+bool Value::Equals(const Value* a, const Value* b) {
+ if ((a == NULL) && (b == NULL)) return true;
+ if ((a == NULL) ^ (b == NULL)) return false;
+ return a->Equals(b);
+}
+
Value::Value(ValueType type) : type_(type) {
}
@@ -674,114 +685,6 @@ void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
}
}
-bool DictionaryValue::GetDifferingPathsHelper(
- const std::string& path_prefix,
- const DictionaryValue* other,
- std::vector<std::string>* different_paths) const {
- bool added_path = false;
- std::map<std::string, Value*>::const_iterator current_this;
- std::map<std::string, Value*>::const_iterator end_this;
- current_this = dictionary_.begin();
- end_this = dictionary_.end();
- if (!other) {
- // Recursively add all paths from the |this| dictionary, since they are
- // not in |other|.
- for (; current_this != end_this; ++current_this) {
- std::string full_path_for_key(path_prefix.empty() ? current_this->first :
- path_prefix + "." + current_this->first);
- different_paths->push_back(full_path_for_key);
- added_path = true;
- if (current_this->second->IsType(Value::TYPE_DICTIONARY)) {
- const DictionaryValue* dictionary_this =
- static_cast<const DictionaryValue*>(current_this->second);
- dictionary_this->GetDifferingPathsHelper(full_path_for_key,
- NULL,
- different_paths);
- }
- }
- } else {
- // Both the |this| and |other| dictionaries have entries. Iterate over
- // both simultaneously. Paths that are in one but not the other are
- // added to |different_paths| and DictionaryValues are processed
- // recursively.
- std::map<std::string, Value*>::const_iterator current_other =
- other->dictionary_.begin();
- std::map<std::string, Value*>::const_iterator end_other =
- other->dictionary_.end();
- while (current_this != end_this || current_other != end_other) {
- const Value* recursion_this = NULL;
- const Value* recursion_other = NULL;
- const std::string* key_name = NULL;
- bool current_value_known_equal = false;
- if (current_this == end_this ||
- (current_other != end_other &&
- (current_other->first < current_this->first))) {
- key_name = &current_other->first;
- if (current_other->second->IsType(Value::TYPE_DICTIONARY))
- recursion_this = current_other->second;
- ++current_other;
- } else {
- key_name = &current_this->first;
- if (current_other == end_other ||
- current_this->first < current_other->first) {
- if (current_this->second->IsType(Value::TYPE_DICTIONARY))
- recursion_this = current_this->second;
- ++current_this;
- } else {
- DCHECK(current_this->first == current_other->first);
- if (current_this->second->IsType(Value::TYPE_DICTIONARY)) {
- recursion_this = current_this->second;
- if (current_other->second->IsType(Value::TYPE_DICTIONARY)) {
- recursion_other = current_other->second;
- }
- } else {
- if (current_other->second->IsType(Value::TYPE_DICTIONARY)) {
- recursion_this = current_other->second;
- } else {
- current_value_known_equal =
- current_this->second->Equals(current_other->second);
- }
- }
- ++current_this;
- ++current_other;
- }
- }
- const std::string& full_path_for_key(path_prefix.empty() ?
- *key_name : path_prefix + "." + *key_name);
- if (!current_value_known_equal)
- different_paths->push_back(full_path_for_key);
- if (recursion_this) {
- const DictionaryValue* dictionary_this =
- static_cast<const DictionaryValue*>(recursion_this);
- bool subtree_changed = dictionary_this->GetDifferingPathsHelper(
- full_path_for_key,
- static_cast<const DictionaryValue*>(recursion_other),
- different_paths);
- if (subtree_changed) {
- added_path = true;
- } else {
- // In order to maintain lexicographical sorting order, directory
- // paths are pushed "optimistically" assuming that their subtree will
- // contain differences. If in retrospect there were no differences
- // in the subtree, the assumption was false and the dictionary path
- // must be removed.
- different_paths->pop_back();
- }
- } else {
- added_path |= !current_value_known_equal;
- }
- }
- }
- return added_path;
-}
-
-void DictionaryValue::GetDifferingPaths(
- const DictionaryValue* other,
- std::vector<std::string>* different_paths) const {
- different_paths->clear();
- GetDifferingPathsHelper("", other, different_paths);
-}
-
///////////////////// ListValue ////////////////////
ListValue::ListValue() : Value(TYPE_LIST) {
@@ -954,6 +857,12 @@ bool ListValue::Insert(size_t index, Value* in_value) {
return true;
}
+bool ListValue::GetAsList(ListValue** out_value) {
+ if (out_value)
+ *out_value = this;
+ return true;
+}
+
Value* ListValue::DeepCopy() const {
ListValue* result = new ListValue;
diff --git a/base/values.h b/base/values.h
index 07d4985..2719d27 100644
--- a/base/values.h
+++ b/base/values.h
@@ -92,6 +92,7 @@ class Value {
virtual bool GetAsReal(double* out_value) const;
virtual bool GetAsString(std::string* out_value) const;
virtual bool GetAsString(string16* out_value) const;
+ virtual bool GetAsList(ListValue** out_value);
// This creates a deep copy of the entire Value tree, and returns a pointer
// to the copy. The caller gets ownership of the copy, of course.
@@ -100,6 +101,10 @@ class Value {
// Compares if two Value objects have equal contents.
virtual bool Equals(const Value* other) const;
+ // Compares if two Value objects have equal contents. Can handle NULLs.
+ // NULLs are considered equal but different from Value::CreateNullValue().
+ static bool Equals(const Value* a, const Value* b);
+
protected:
// This isn't safe for end-users (they should use the Create*Value()
// static methods above), but it's useful for subclasses.
@@ -119,7 +124,7 @@ class FundamentalValue : public Value {
explicit FundamentalValue(bool in_value);
explicit FundamentalValue(int in_value);
explicit FundamentalValue(double in_value);
- ~FundamentalValue();
+ virtual ~FundamentalValue();
// Subclassed methods
virtual bool GetAsBoolean(bool* out_value) const;
@@ -146,12 +151,12 @@ class StringValue : public Value {
// Initializes a StringValue with a string16.
explicit StringValue(const string16& in_value);
- ~StringValue();
+ virtual ~StringValue();
// Subclassed methods
- bool GetAsString(std::string* out_value) const;
- bool GetAsString(string16* out_value) const;
- Value* DeepCopy() const;
+ virtual bool GetAsString(std::string* out_value) const;
+ virtual bool GetAsString(string16* out_value) const;
+ virtual Value* DeepCopy() const;
virtual bool Equals(const Value* other) const;
private:
@@ -173,10 +178,10 @@ class BinaryValue: public Value {
// Returns NULL if buffer is NULL.
static BinaryValue* CreateWithCopiedBuffer(const char* buffer, size_t size);
- ~BinaryValue();
+ virtual ~BinaryValue();
// Subclassed methods
- Value* DeepCopy() const;
+ virtual Value* DeepCopy() const;
virtual bool Equals(const Value* other) const;
size_t GetSize() const { return size_; }
@@ -200,10 +205,10 @@ class BinaryValue: public Value {
class DictionaryValue : public Value {
public:
DictionaryValue();
- ~DictionaryValue();
+ virtual ~DictionaryValue();
// Subclassed methods
- Value* DeepCopy() const;
+ virtual Value* DeepCopy() const;
virtual bool Equals(const Value* other) const;
// Returns true if the current dictionary has a value for the given key.
@@ -303,16 +308,6 @@ class DictionaryValue : public Value {
// replaced.
void MergeDictionary(const DictionaryValue* dictionary);
- // Builds a vector containing all of the paths that are different between
- // the dictionary and a second specified dictionary. These are paths of
- // values that are either in one dictionary or the other but not both, OR
- // paths that are present in both dictionaries but differ in value.
- // Path strings are in ascending lexicographical order in the generated
- // vector. |different_paths| is cleared before added any paths.
- void GetDifferingPaths(
- const DictionaryValue* other,
- std::vector<std::string>* different_paths) const;
-
// This class provides an iterator for the keys in the dictionary.
// It can't be used to modify the dictionary.
//
@@ -339,17 +334,6 @@ class DictionaryValue : public Value {
key_iterator end_keys() const { return key_iterator(dictionary_.end()); }
private:
- // Does the actual heavy lifting for GetDifferingPaths.
- // Returns true if a path is added to different_paths, otherwise false.
- // The difference compuation is calculated recursively. The keys for
- // dictionaries that are handled by recursive calls more shallow than
- // the current one are concatenated and passed through to deeper calls in
- // |path_prefix|.
- bool GetDifferingPathsHelper(
- const std::string& path_prefix,
- const DictionaryValue* other,
- std::vector<std::string>* different_paths) const;
-
ValueMap dictionary_;
DISALLOW_COPY_AND_ASSIGN(DictionaryValue);
@@ -362,7 +346,8 @@ class ListValue : public Value {
~ListValue();
// Subclassed methods
- Value* DeepCopy() const;
+ virtual bool GetAsList(ListValue** out_value);
+ virtual Value* DeepCopy() const;
virtual bool Equals(const Value* other) const;
// Clears the contents of this ListValue
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index 9f34c62..adcd07e 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -10,27 +10,7 @@
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
-class ValuesTest: public testing::Test {
- protected:
- void CompareDictionariesAndCheckResult(
- const DictionaryValue* dict1,
- const DictionaryValue* dict2,
- const char* expected_paths[],
- size_t expected_paths_count) {
- std::vector<std::string> differing_paths;
- std::vector<std::string> expected_paths_vector(expected_paths,
- expected_paths+expected_paths_count);
- // All comparisons should be commutative, check dict1 against dict2
- // and vice-versa.
- dict1->GetDifferingPaths(dict2, &differing_paths);
- ASSERT_EQ(expected_paths_count, differing_paths.size());
- EXPECT_TRUE(equal(differing_paths.begin(), differing_paths.end(),
- expected_paths_vector.begin()));
- dict2->GetDifferingPaths(dict1, &differing_paths);
- ASSERT_EQ(expected_paths_count, differing_paths.size());
- EXPECT_TRUE(equal(differing_paths.begin(), differing_paths.end(),
- expected_paths_vector.begin()));
- }
+class ValuesTest : public testing::Test {
};
TEST_F(ValuesTest, Basic) {
@@ -508,6 +488,29 @@ TEST_F(ValuesTest, Equals) {
EXPECT_FALSE(dv.Equals(copy.get()));
}
+TEST_F(ValuesTest, StaticEquals) {
+ scoped_ptr<Value> null1(Value::CreateNullValue());
+ scoped_ptr<Value> null2(Value::CreateNullValue());
+ EXPECT_TRUE(Value::Equals(null1.get(), null2.get()));
+ EXPECT_TRUE(Value::Equals(NULL, NULL));
+
+ scoped_ptr<Value> i42(Value::CreateIntegerValue(42));
+ scoped_ptr<Value> j42(Value::CreateIntegerValue(42));
+ scoped_ptr<Value> i17(Value::CreateIntegerValue(17));
+ EXPECT_TRUE(Value::Equals(i42.get(), i42.get()));
+ EXPECT_TRUE(Value::Equals(j42.get(), i42.get()));
+ EXPECT_TRUE(Value::Equals(i42.get(), j42.get()));
+ EXPECT_FALSE(Value::Equals(i42.get(), i17.get()));
+ EXPECT_FALSE(Value::Equals(i42.get(), NULL));
+ EXPECT_FALSE(Value::Equals(NULL, i42.get()));
+
+ // NULL and Value::CreateNullValue() are intentionally different: We need
+ // support for NULL as a return value for "undefined" without caring for
+ // ownership of the pointer.
+ EXPECT_FALSE(Value::Equals(null1.get(), NULL));
+ EXPECT_FALSE(Value::Equals(NULL, null1.get()));
+}
+
TEST_F(ValuesTest, RemoveEmptyChildren) {
scoped_ptr<DictionaryValue> root(new DictionaryValue);
// Remove empty lists and dictionaries.
@@ -627,114 +630,3 @@ TEST_F(ValuesTest, MergeDictionary) {
EXPECT_TRUE(res_sub_dict->GetString("sub_merge_key", &sub_merge_key_value));
EXPECT_EQ("sub_merge_key_value_merge", sub_merge_key_value); // Merged in.
}
-
-TEST_F(ValuesTest, GetDifferingPaths) {
- scoped_ptr<DictionaryValue> dict1(new DictionaryValue());
- scoped_ptr<DictionaryValue> dict2(new DictionaryValue());
- std::vector<std::string> differing_paths;
-
- // Test comparing empty dictionaries.
- dict1->GetDifferingPaths(dict2.get(), &differing_paths);
- EXPECT_EQ(differing_paths.size(), 0UL);
-
- // Compare an empty dictionary with various non-empty dictionaries.
- static const char* expected_paths1[] = {
- "segment1"
- };
- dict1->SetString("segment1", "value1");
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths1,
- arraysize(expected_paths1));
-
- static const char* expected_paths2[] = {
- "segment1",
- "segment2",
- "segment2.segment3"
- };
- dict1->SetString("segment2.segment3", "value2");
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths2,
- arraysize(expected_paths2));
-
- static const char* expected_paths3[] = {
- "segment1",
- "segment2",
- "segment2.segment3",
- "segment4",
- "segment4.segment5"
- };
- dict1->SetString("segment4.segment5", "value3");
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths3,
- arraysize(expected_paths3));
-
- // Now various tests with two populated dictionaries.
- static const char* expected_paths4[] = {
- "segment1",
- "segment2",
- "segment2.segment3",
- "segment4",
- "segment4.segment5"
- };
- dict2->Set("segment2", new DictionaryValue());
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths4,
- arraysize(expected_paths4));
-
- static const char* expected_paths5[] = {
- "segment1",
- "segment4",
- "segment4.segment5"
- };
- dict2->SetString("segment2.segment3", "value2");
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths5,
- arraysize(expected_paths5));
-
- dict2->SetBoolean("segment2.segment3", true);
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths4,
- arraysize(expected_paths4));
-
- // Test two identical dictionaries.
- dict2.reset(static_cast<DictionaryValue*>(dict1->DeepCopy()));
- dict2->GetDifferingPaths(dict1.get(), &differing_paths);
- EXPECT_EQ(differing_paths.size(), 0UL);
-
- // Test a deep dictionary structure.
- static const char* expected_paths6[] = {
- "s1",
- "s1.s2",
- "s1.s2.s3",
- "s1.s2.s3.s4",
- "s1.s2.s3.s4.s5"
- };
- dict1.reset(new DictionaryValue());
- dict2.reset(new DictionaryValue());
- dict1->Set("s1.s2.s3.s4.s5", new DictionaryValue());
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths6,
- arraysize(expected_paths6));
-
- // Make sure disjoint dictionaries generate the right differing path list.
- static const char* expected_paths7[] = {
- "a",
- "b",
- "c",
- "d"
- };
- dict1.reset(new DictionaryValue());
- dict1->SetBoolean("a", true);
- dict1->SetBoolean("c", true);
- dict2.reset(new DictionaryValue());
- dict1->SetBoolean("b", true);
- dict1->SetBoolean("d", true);
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths7,
- arraysize(expected_paths7));
-
- // For code coverage completeness. Make sure that all branches
- // that were not covered are executed.
- static const char* expected_paths8[] = {
- "s1",
- "s1.s2"
- };
- dict1.reset(new DictionaryValue());
- dict1->Set("s1.s2", new DictionaryValue());
- dict2.reset(new DictionaryValue());
- dict2->SetInteger("s1", 1);
- CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths8,
- arraysize(expected_paths8));
-}
diff --git a/base/values_util.cc b/base/values_util.cc
index 31d8e8c..fbc616b 100644
--- a/base/values_util.cc
+++ b/base/values_util.cc
@@ -12,3 +12,7 @@ RefCountedList::~RefCountedList() {
if (list_)
delete list_;
}
+
+ListValue* RefCountedList::Get() {
+ return list_;
+}
diff --git a/base/values_util.h b/base/values_util.h
index 57b35c1..1626bb5 100644
--- a/base/values_util.h
+++ b/base/values_util.h
@@ -15,9 +15,7 @@ class RefCountedList : public base::RefCountedThreadSafe<RefCountedList> {
explicit RefCountedList(ListValue* list);
virtual ~RefCountedList();
- virtual ListValue* Get() {
- return list_;
- }
+ virtual ListValue* Get();
private:
ListValue* list_;
diff --git a/base/version.cc b/base/version.cc
index fe224eb..384be0a 100644
--- a/base/version.cc
+++ b/base/version.cc
@@ -4,6 +4,8 @@
#include "base/version.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/string_split.h"
@@ -11,13 +13,6 @@
#include "base/utf_string_conversions.h"
// static
-Version* Version::GetVersionFromString(const std::wstring& version_str) {
- if (!IsStringASCII(version_str))
- return NULL;
- return GetVersionFromString(WideToUTF8(version_str));
-}
-
-// static
Version* Version::GetVersionFromString(const std::string& version_str) {
Version* vers = new Version();
if (vers->InitFromString(version_str)) {
@@ -32,6 +27,14 @@ Version::Version() : is_valid_(false) {}
Version::~Version() {}
+Version* Version::Clone() const {
+ DCHECK(is_valid_);
+ Version* copy = new Version();
+ copy->components_ = components_;
+ copy->is_valid_ = true;
+ return copy;
+}
+
bool Version::Equals(const Version& that) const {
DCHECK(is_valid_);
DCHECK(that.is_valid_);
diff --git a/base/version.h b/base/version.h
index 2b182bb..2fda4ad 100644
--- a/base/version.h
+++ b/base/version.h
@@ -12,12 +12,14 @@
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
+// Version represents a dotted version number, like "1.2.3.4", supporting
+// parsing and comparison.
+// Each component is limited to a uint16.
class Version {
public:
// The version string must be made up of 1 or more uint16's separated
// by '.'. Returns NULL if string is not in this format.
// Caller is responsible for freeing the Version object once done.
- static Version* GetVersionFromString(const std::wstring& version_str);
static Version* GetVersionFromString(const std::string& version_str);
// Exposed only so that a Version can be stored in STL containers;
@@ -27,6 +29,9 @@ class Version {
~Version();
+ // Creates a copy of this version. Caller takes ownership.
+ Version* Clone() const;
+
bool Equals(const Version& other) const;
// Returns -1, 0, 1 for <, ==, >.
diff --git a/base/waitable_event_watcher.h b/base/waitable_event_watcher.h
index b6f5e9e..04aa8cf 100644
--- a/base/waitable_event_watcher.h
+++ b/base/waitable_event_watcher.h
@@ -145,7 +145,7 @@ class WaitableEventWatcher
// ---------------------------------------------------------------------------
// Implementation of MessageLoop::DestructionObserver
// ---------------------------------------------------------------------------
- void WillDestroyCurrentMessageLoop();
+ virtual void WillDestroyCurrentMessageLoop();
MessageLoop* message_loop_;
scoped_refptr<Flag> cancel_flag_;
diff --git a/base/watchdog_unittest.cc b/base/watchdog_unittest.cc
index 19dfe28..658a31a 100644
--- a/base/watchdog_unittest.cc
+++ b/base/watchdog_unittest.cc
@@ -86,7 +86,7 @@ TEST_F(WatchdogTest, AlarmTest) {
// Make sure a basic alarm fires when the time has expired.
TEST_F(WatchdogTest, AlarmPriorTimeTest) {
- WatchdogCounter watchdog(TimeDelta::TimeDelta(), "Enabled2", true);
+ WatchdogCounter watchdog(TimeDelta(), "Enabled2", true);
// Set a time in the past.
watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2));
// It should instantly go off, but certainly in less than 5 minutes.
diff --git a/base/win/registry.cc b/base/win/registry.cc
index 3372cf4..f8e05a7 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -244,7 +244,7 @@ bool RegKey::OpenKey(const wchar_t* name, REGSAM access) {
return (result == ERROR_SUCCESS);
}
-DWORD RegKey::ValueCount() {
+DWORD RegKey::ValueCount() const {
base::ThreadRestrictions::AssertIOAllowed();
DWORD count = 0;
HRESULT result = RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL,
@@ -252,7 +252,7 @@ DWORD RegKey::ValueCount() {
return (result != ERROR_SUCCESS) ? 0 : count;
}
-bool RegKey::ReadName(int index, std::wstring* name) {
+bool RegKey::ReadName(int index, std::wstring* name) const {
base::ThreadRestrictions::AssertIOAllowed();
wchar_t buf[256];
DWORD bufsize = arraysize(buf);
@@ -274,7 +274,7 @@ bool RegKey::ValueExists(const wchar_t* name) {
}
bool RegKey::ReadValue(const wchar_t* name, void* data,
- DWORD* dsize, DWORD* dtype) {
+ DWORD* dsize, DWORD* dtype) const {
base::ThreadRestrictions::AssertIOAllowed();
if (!key_)
return false;
@@ -283,7 +283,7 @@ bool RegKey::ReadValue(const wchar_t* name, void* data,
return (result == ERROR_SUCCESS);
}
-bool RegKey::ReadValue(const wchar_t* name, std::wstring* value) {
+bool RegKey::ReadValue(const wchar_t* name, std::wstring* value) const {
base::ThreadRestrictions::AssertIOAllowed();
DCHECK(value);
const size_t kMaxStringLength = 1024; // This is after expansion.
@@ -312,7 +312,7 @@ bool RegKey::ReadValue(const wchar_t* name, std::wstring* value) {
return false;
}
-bool RegKey::ReadValueDW(const wchar_t* name, DWORD* value) {
+bool RegKey::ReadValueDW(const wchar_t* name, DWORD* value) const {
DCHECK(value);
DWORD type = REG_DWORD;
DWORD size = sizeof(DWORD);
diff --git a/base/win/registry.h b/base/win/registry.h
index d1ef25b..96a2bb3 100644
--- a/base/win/registry.h
+++ b/base/win/registry.h
@@ -38,10 +38,10 @@ class RegKey {
void Close();
- DWORD ValueCount();
+ DWORD ValueCount() const;
// Determine the nth value's name.
- bool ReadName(int index, std::wstring* name);
+ bool ReadName(int index, std::wstring* name) const;
// True while the key is valid.
bool Valid() const { return key_ != NULL; }
@@ -55,9 +55,10 @@ class RegKey {
bool ValueExists(const wchar_t* name);
- bool ReadValue(const wchar_t* name, void* data, DWORD* dsize, DWORD* dtype);
- bool ReadValue(const wchar_t* name, std::wstring* value);
- bool ReadValueDW(const wchar_t* name, DWORD* value);
+ bool ReadValue(const wchar_t* name, void* data, DWORD* dsize,
+ DWORD* dtype) const;
+ bool ReadValue(const wchar_t* name, std::wstring* value) const;
+ bool ReadValueDW(const wchar_t* name, DWORD* value) const;
bool WriteValue(const wchar_t* name, const void* data, DWORD dsize,
DWORD dtype);
@@ -65,7 +66,7 @@ class RegKey {
bool WriteValue(const wchar_t* name, DWORD value);
// Starts watching the key to see if any of its values have changed.
- // The key must have been opened with the KEY_NOTIFY access privelege.
+ // The key must have been opened with the KEY_NOTIFY access privilege.
bool StartWatching();
// If StartWatching hasn't been called, always returns false.
diff --git a/base/win/scoped_variant.cc b/base/win/scoped_variant.cc
index 278e976..40ccdf2 100644
--- a/base/win/scoped_variant.cc
+++ b/base/win/scoped_variant.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/scoped_variant_win.h"
+#include "base/win/scoped_variant.h"
#include "base/logging.h"
namespace base {
diff --git a/base/worker_pool_mac.h b/base/worker_pool_mac.h
deleted file mode 100644
index 1e86891..0000000
--- a/base/worker_pool_mac.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2009 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_WORKER_POOL_MAC_H_
-#define BASE_WORKER_POOL_MAC_H_
-#pragma once
-
-#include "base/worker_pool.h"
-
-#import <Foundation/Foundation.h>
-
-// WorkerPoolObjC provides an Objective-C interface to the same WorkerPool
-// used by the rest of the application.
-@interface WorkerPoolObjC : NSObject
-
-// Returns the underlying NSOperationQueue back end that WorkerPool::PostTask
-// would post tasks to. This can be used to add NSOperation subclasses
-// directly to the same NSOperationQueue, by calling -[NSOperationQueue
-// addOperation:]. Most Objective-C code wishing to dispatch tasks to the
-// WorkerPool will find it handy to add an operation of type
-// NSInvocationOperation.
-+ (NSOperationQueue*)sharedOperationQueue;
-
-@end // @interface WorkerPoolObjC
-
-namespace worker_pool_mac {
-
-void SetUseLinuxWorkerPool(bool flag);
-
-} // namespace worker_pool_mac
-
-#endif // BASE_WORKER_POOL_MAC_H_
diff --git a/base/worker_pool_mac.mm b/base/worker_pool_mac.mm
deleted file mode 100644
index bbc7892..0000000
--- a/base/worker_pool_mac.mm
+++ /dev/null
@@ -1,205 +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/worker_pool_mac.h"
-
-#include "base/logging.h"
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/metrics/histogram.h"
-#include "base/scoped_ptr.h"
-#import "base/singleton_objc.h"
-#include "base/task.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/worker_pool_linux.h"
-
-// When C++ exceptions are disabled, the C++ library defines |try| and
-// |catch| so as to allow exception-expecting C++ code to build properly when
-// language support for exceptions is not present. These macros interfere
-// with the use of |@try| and |@catch| in Objective-C files such as this one.
-// Undefine these macros here, after everything has been #included, since
-// there will be no C++ uses and only Objective-C uses from this point on.
-#undef try
-#undef catch
-
-namespace {
-
-// |true| to use the Linux WorkerPool implementation for
-// |WorkerPool::PostTask()|.
-bool use_linux_workerpool_ = true;
-
-Lock lock_;
-base::Time last_check_; // Last hung-test check.
-std::vector<id> outstanding_ops_; // Outstanding operations at last check.
-size_t running_ = 0; // Operations in |Run()|.
-size_t outstanding_ = 0; // Operations posted but not completed.
-
-} // namespace
-
-namespace worker_pool_mac {
-
-void SetUseLinuxWorkerPool(bool flag) {
- use_linux_workerpool_ = flag;
-}
-
-} // namespace worker_pool_mac
-
-@implementation WorkerPoolObjC
-
-+ (NSOperationQueue*)sharedOperationQueue {
- return SingletonObjC<NSOperationQueue>::get();
-}
-
-@end // @implementation WorkerPoolObjC
-
-// TaskOperation adapts Task->Run() for use in an NSOperationQueue.
-@interface TaskOperation : NSOperation {
- @private
- scoped_ptr<Task> task_;
-}
-
-// Returns an autoreleased instance of TaskOperation. See -initWithTask: for
-// details.
-+ (id)taskOperationWithTask:(Task*)task;
-
-// Designated initializer. |task| is adopted as the Task* whose Run method
-// this operation will call when executed.
-- (id)initWithTask:(Task*)task;
-
-@end // @interface TaskOperation
-
-@implementation TaskOperation
-
-+ (id)taskOperationWithTask:(Task*)task {
- return [[[TaskOperation alloc] initWithTask:task] autorelease];
-}
-
-- (id)init {
- return [self initWithTask:NULL];
-}
-
-- (id)initWithTask:(Task*)task {
- if ((self = [super init])) {
- task_.reset(task);
- }
- return self;
-}
-
-- (void)main {
- DCHECK(task_.get()) << "-[TaskOperation main] called with no task";
- if (!task_.get()) {
- return;
- }
-
- {
- AutoLock locked(lock_);
- ++running_;
- }
-
- base::mac::ScopedNSAutoreleasePool autoreleasePool;
-
- @try {
- task_->Run();
- } @catch(NSException* exception) {
- LOG(ERROR) << "-[TaskOperation main] caught an NSException: "
- << [[exception description] UTF8String];
- } @catch(id exception) {
- LOG(ERROR) << "-[TaskOperation main] caught an unknown exception";
- }
-
- task_.reset(NULL);
-
- {
- AutoLock locked(lock_);
- --running_;
- --outstanding_;
- }
-}
-
-- (void)dealloc {
- // Getting the task_ contents without a lock can lead to a benign data race.
- // We annotate it to stay silent under ThreadSanitizer.
- ANNOTATE_IGNORE_READS_BEGIN();
- DCHECK(!task_.get())
- << "-[TaskOperation dealloc] called without running task";
- ANNOTATE_IGNORE_READS_END();
- [super dealloc];
-}
-
-@end // @implementation TaskOperation
-
-bool WorkerPool::PostTask(const tracked_objects::Location& from_here,
- Task* task, bool task_is_slow) {
- if (use_linux_workerpool_) {
- return worker_pool_mac::MacPostTaskHelper(from_here, task, task_is_slow);
- }
-
- base::mac::ScopedNSAutoreleasePool autorelease_pool;
-
- // Ignore |task_is_slow|, it doesn't map directly to any tunable aspect of
- // an NSOperation.
-
- DCHECK(task) << "WorkerPool::PostTask called with no task";
- if (!task) {
- return false;
- }
-
- task->SetBirthPlace(from_here);
-
- NSOperationQueue* operation_queue = [WorkerPoolObjC sharedOperationQueue];
- [operation_queue addOperation:[TaskOperation taskOperationWithTask:task]];
-
- if ([operation_queue isSuspended]) {
- LOG(WARNING) << "WorkerPool::PostTask freeing stuck NSOperationQueue";
-
- // Nothing should ever be suspending this queue, but in case it winds up
- // happening, free things up. This is a purely speculative shot in the
- // dark for http://crbug.com/20471.
- [operation_queue setSuspended:NO];
- }
-
- // Periodically calculate the set of operations which have not made
- // progress and report how many there are. This should provide a
- // sense of how many clients are seeing hung operations of any sort,
- // and a sense of how many clients are seeing "too many" hung
- // operations.
- std::vector<id> hung_ops;
- size_t outstanding_delta = 0;
- size_t running_ops = 0;
- {
- const base::TimeDelta kCheckPeriod(base::TimeDelta::FromMinutes(10));
- base::Time now = base::Time::Now();
-
- AutoLock locked(lock_);
- ++outstanding_;
- running_ops = running_;
- if (last_check_.is_null() || now - last_check_ > kCheckPeriod) {
- base::mac::ScopedNSAutoreleasePool autoreleasePool;
- std::vector<id> ops;
- for (id op in [operation_queue operations]) {
- // DO NOT RETAIN.
- ops.push_back(op);
- }
- std::sort(ops.begin(), ops.end());
-
- outstanding_delta = outstanding_ - ops.size();
-
- std::set_intersection(outstanding_ops_.begin(), outstanding_ops_.end(),
- ops.begin(), ops.end(),
- std::back_inserter(hung_ops));
-
- outstanding_ops_.swap(ops);
- last_check_ = now;
- }
- }
-
- // Don't report "nothing to report".
- const size_t kUnaccountedOpsDelta = 10;
- if (hung_ops.size() > 0 || outstanding_delta > kUnaccountedOpsDelta) {
- UMA_HISTOGRAM_COUNTS_100("OSX.HungWorkers", hung_ops.size());
- UMA_HISTOGRAM_COUNTS_100("OSX.OutstandingDelta", outstanding_delta);
- UMA_HISTOGRAM_COUNTS_100("OSX.RunningOps", running_ops);
- }
-
- return true;
-}
diff --git a/base/worker_pool_linux.cc b/base/worker_pool_posix.cc
index 8c96ca0..85e1d8e 100644
--- a/base/worker_pool_linux.cc
+++ b/base/worker_pool_posix.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/worker_pool.h"
-#include "base/worker_pool_linux.h"
+#include "base/worker_pool_posix.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
@@ -28,11 +28,11 @@ class WorkerPoolImpl {
bool task_is_slow);
private:
- scoped_refptr<base::LinuxDynamicThreadPool> pool_;
+ scoped_refptr<base::PosixDynamicThreadPool> pool_;
};
WorkerPoolImpl::WorkerPoolImpl()
- : pool_(new base::LinuxDynamicThreadPool(
+ : pool_(new base::PosixDynamicThreadPool(
"WorkerPool", kIdleSecondsBeforeExit)) {}
WorkerPoolImpl::~WorkerPoolImpl() {
@@ -50,7 +50,7 @@ base::LazyInstance<WorkerPoolImpl> g_lazy_worker_pool(base::LINKER_INITIALIZED);
class WorkerThread : public PlatformThread::Delegate {
public:
WorkerThread(const std::string& name_prefix, int idle_seconds_before_exit,
- base::LinuxDynamicThreadPool* pool)
+ base::PosixDynamicThreadPool* pool)
: name_prefix_(name_prefix),
idle_seconds_before_exit_(idle_seconds_before_exit),
pool_(pool) {}
@@ -60,7 +60,7 @@ class WorkerThread : public PlatformThread::Delegate {
private:
const std::string name_prefix_;
const int idle_seconds_before_exit_;
- scoped_refptr<base::LinuxDynamicThreadPool> pool_;
+ scoped_refptr<base::PosixDynamicThreadPool> pool_;
DISALLOW_COPY_AND_ASSIGN(WorkerThread);
};
@@ -84,33 +84,15 @@ void WorkerThread::ThreadMain() {
} // namespace
-// NOTE(shess): Temporarily allow the Mac WorkerPool implementation to
-// call into the linux so that it can provide a command-line flag for
-// switching back and forth. After evaluating, either remove the
-// ifdef, or shift this to a shared POSIX implementation.
-// http://crbug.com/44392
-#if defined(OS_MACOSX)
-namespace worker_pool_mac {
-
-bool MacPostTaskHelper(const tracked_objects::Location& from_here,
- Task* task, bool task_is_slow) {
- g_lazy_worker_pool.Pointer()->PostTask(from_here, task, task_is_slow);
- return true;
-}
-
-} // namespace worker_pool_mac
-
-#else
bool WorkerPool::PostTask(const tracked_objects::Location& from_here,
Task* task, bool task_is_slow) {
g_lazy_worker_pool.Pointer()->PostTask(from_here, task, task_is_slow);
return true;
}
-#endif
namespace base {
-LinuxDynamicThreadPool::LinuxDynamicThreadPool(
+PosixDynamicThreadPool::PosixDynamicThreadPool(
const std::string& name_prefix,
int idle_seconds_before_exit)
: name_prefix_(name_prefix),
@@ -120,7 +102,7 @@ LinuxDynamicThreadPool::LinuxDynamicThreadPool(
terminated_(false),
num_idle_threads_cv_(NULL) {}
-LinuxDynamicThreadPool::~LinuxDynamicThreadPool() {
+PosixDynamicThreadPool::~PosixDynamicThreadPool() {
while (!tasks_.empty()) {
Task* task = tasks_.front();
tasks_.pop();
@@ -128,7 +110,7 @@ LinuxDynamicThreadPool::~LinuxDynamicThreadPool() {
}
}
-void LinuxDynamicThreadPool::Terminate() {
+void PosixDynamicThreadPool::Terminate() {
{
AutoLock locked(lock_);
DCHECK(!terminated_) << "Thread pool is already terminated.";
@@ -137,7 +119,7 @@ void LinuxDynamicThreadPool::Terminate() {
tasks_available_cv_.Broadcast();
}
-void LinuxDynamicThreadPool::PostTask(Task* task) {
+void PosixDynamicThreadPool::PostTask(Task* task) {
AutoLock locked(lock_);
DCHECK(!terminated_) <<
"This thread pool is already terminated. Do not post new tasks.";
@@ -156,7 +138,7 @@ void LinuxDynamicThreadPool::PostTask(Task* task) {
}
}
-Task* LinuxDynamicThreadPool::WaitForTask() {
+Task* PosixDynamicThreadPool::WaitForTask() {
AutoLock locked(lock_);
if (terminated_)
diff --git a/base/worker_pool_linux.h b/base/worker_pool_posix.h
index ea6bab7..73d8287 100644
--- a/base/worker_pool_linux.h
+++ b/base/worker_pool_posix.h
@@ -2,27 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// The thread pool used in the Linux implementation of WorkerPool dynamically
+// The thread pool used in the POSIX implementation of WorkerPool dynamically
// adds threads as necessary to handle all tasks. It keeps old threads around
// for a period of time to allow them to be reused. After this waiting period,
// the threads exit. This thread pool uses non-joinable threads, therefore
// worker threads are not joined during process shutdown. This means that
// potentially long running tasks (such as DNS lookup) do not block process
// shutdown, but also means that process shutdown may "leak" objects. Note that
-// although LinuxDynamicThreadPool spawns the worker threads and manages the
+// although PosixDynamicThreadPool spawns the worker threads and manages the
// task queue, it does not own the worker threads. The worker threads ask the
-// LinuxDynamicThreadPool for work and eventually clean themselves up. The
-// worker threads all maintain scoped_refptrs to the LinuxDynamicThreadPool
-// instance, which prevents LinuxDynamicThreadPool from disappearing before all
-// worker threads exit. The owner of LinuxDynamicThreadPool should likewise
-// maintain a scoped_refptr to the LinuxDynamicThreadPool instance.
+// PosixDynamicThreadPool for work and eventually clean themselves up. The
+// worker threads all maintain scoped_refptrs to the PosixDynamicThreadPool
+// instance, which prevents PosixDynamicThreadPool from disappearing before all
+// worker threads exit. The owner of PosixDynamicThreadPool should likewise
+// maintain a scoped_refptr to the PosixDynamicThreadPool instance.
//
-// NOTE: The classes defined in this file are only meant for use by the Linux
+// NOTE: The classes defined in this file are only meant for use by the POSIX
// implementation of WorkerPool. No one else should be using these classes.
// These symbols are exported in a header purely for testing purposes.
-#ifndef BASE_WORKER_POOL_LINUX_H_
-#define BASE_WORKER_POOL_LINUX_H_
+#ifndef BASE_WORKER_POOL_POSIX_H_
+#define BASE_WORKER_POOL_POSIX_H_
#pragma once
#include <queue>
@@ -39,22 +39,22 @@ class Task;
namespace base {
-class LinuxDynamicThreadPool
- : public RefCountedThreadSafe<LinuxDynamicThreadPool> {
+class PosixDynamicThreadPool
+ : public RefCountedThreadSafe<PosixDynamicThreadPool> {
public:
- class LinuxDynamicThreadPoolPeer;
+ class PosixDynamicThreadPoolPeer;
// All worker threads will share the same |name_prefix|. They will exit after
// |idle_seconds_before_exit|.
- LinuxDynamicThreadPool(const std::string& name_prefix,
+ PosixDynamicThreadPool(const std::string& name_prefix,
int idle_seconds_before_exit);
- ~LinuxDynamicThreadPool();
+ ~PosixDynamicThreadPool();
// Indicates that the thread pool is going away. Stops handing out tasks to
// worker threads. Wakes up all the idle threads to let them exit.
void Terminate();
- // Adds |task| to the thread pool. LinuxDynamicThreadPool assumes ownership
+ // Adds |task| to the thread pool. PosixDynamicThreadPool assumes ownership
// of |task|.
void PostTask(Task* task);
@@ -63,7 +63,7 @@ class LinuxDynamicThreadPool
Task* WaitForTask();
private:
- friend class LinuxDynamicThreadPoolPeer;
+ friend class PosixDynamicThreadPoolPeer;
const std::string name_prefix_;
const int idle_seconds_before_exit_;
@@ -81,23 +81,9 @@ class LinuxDynamicThreadPool
// NULL in non-test code.
scoped_ptr<ConditionVariable> num_idle_threads_cv_;
- DISALLOW_COPY_AND_ASSIGN(LinuxDynamicThreadPool);
+ DISALLOW_COPY_AND_ASSIGN(PosixDynamicThreadPool);
};
} // namespace base
-#if defined(OS_MACOSX)
-namespace worker_pool_mac {
-
-// NOTE(shess): Helper so that Mac WorkerPool implementation can call
-// into Linux implementation while determining if the implementations
-// should be merged. After evaluating, either remove the ifdef, or
-// shift this to a shared POSIX implementation.
-// http://crbug.com/44392
-bool MacPostTaskHelper(const tracked_objects::Location& from_here,
- Task* task, bool task_is_slow);
-
-} // namespace worker_pool_mac
-#endif
-
-#endif // BASE_WORKER_POOL_LINUX_H_
+#endif // BASE_WORKER_POOL_POSIX_H_
diff --git a/base/worker_pool_linux_unittest.cc b/base/worker_pool_posix_unittest.cc
index f98f37a..55453c8 100644
--- a/base/worker_pool_linux_unittest.cc
+++ b/base/worker_pool_posix_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/worker_pool_linux.h"
+#include "base/worker_pool_posix.h"
#include <set>
@@ -15,10 +15,10 @@
namespace base {
-// Peer class to provide passthrough access to LinuxDynamicThreadPool internals.
-class LinuxDynamicThreadPool::LinuxDynamicThreadPoolPeer {
+// Peer class to provide passthrough access to PosixDynamicThreadPool internals.
+class PosixDynamicThreadPool::PosixDynamicThreadPoolPeer {
public:
- explicit LinuxDynamicThreadPoolPeer(LinuxDynamicThreadPool* pool)
+ explicit PosixDynamicThreadPoolPeer(PosixDynamicThreadPool* pool)
: pool_(pool) {}
Lock* lock() { return &pool_->lock_; }
@@ -35,9 +35,9 @@ class LinuxDynamicThreadPool::LinuxDynamicThreadPoolPeer {
}
private:
- LinuxDynamicThreadPool* pool_;
+ PosixDynamicThreadPool* pool_;
- DISALLOW_COPY_AND_ASSIGN(LinuxDynamicThreadPoolPeer);
+ DISALLOW_COPY_AND_ASSIGN(PosixDynamicThreadPoolPeer);
};
} // namespace base
@@ -120,10 +120,10 @@ class BlockingIncrementingTask : public Task {
DISALLOW_COPY_AND_ASSIGN(BlockingIncrementingTask);
};
-class LinuxDynamicThreadPoolTest : public testing::Test {
+class PosixDynamicThreadPoolTest : public testing::Test {
protected:
- LinuxDynamicThreadPoolTest()
- : pool_(new base::LinuxDynamicThreadPool("dynamic_pool", 60*60)),
+ PosixDynamicThreadPoolTest()
+ : pool_(new base::PosixDynamicThreadPool("dynamic_pool", 60*60)),
peer_(pool_.get()),
counter_(0),
num_waiting_to_start_(0),
@@ -165,8 +165,8 @@ class LinuxDynamicThreadPoolTest : public testing::Test {
&num_waiting_to_start_cv_, &start_);
}
- scoped_refptr<base::LinuxDynamicThreadPool> pool_;
- base::LinuxDynamicThreadPool::LinuxDynamicThreadPoolPeer peer_;
+ scoped_refptr<base::PosixDynamicThreadPool> pool_;
+ base::PosixDynamicThreadPool::PosixDynamicThreadPoolPeer peer_;
Lock counter_lock_;
int counter_;
Lock unique_threads_lock_;
@@ -177,7 +177,7 @@ class LinuxDynamicThreadPoolTest : public testing::Test {
base::WaitableEvent start_;
};
-TEST_F(LinuxDynamicThreadPoolTest, Basic) {
+TEST_F(PosixDynamicThreadPoolTest, Basic) {
EXPECT_EQ(0, peer_.num_idle_threads());
EXPECT_EQ(0U, unique_threads_.size());
EXPECT_EQ(0U, peer_.tasks().size());
@@ -193,7 +193,7 @@ TEST_F(LinuxDynamicThreadPoolTest, Basic) {
EXPECT_EQ(1, counter_);
}
-TEST_F(LinuxDynamicThreadPoolTest, ReuseIdle) {
+TEST_F(PosixDynamicThreadPoolTest, ReuseIdle) {
// Add one task and wait for it to be completed.
pool_->PostTask(CreateNewIncrementingTask());
@@ -212,7 +212,7 @@ TEST_F(LinuxDynamicThreadPoolTest, ReuseIdle) {
EXPECT_EQ(3, counter_);
}
-TEST_F(LinuxDynamicThreadPoolTest, TwoActiveTasks) {
+TEST_F(PosixDynamicThreadPoolTest, TwoActiveTasks) {
// Add two blocking tasks.
pool_->PostTask(CreateNewBlockingIncrementingTask());
pool_->PostTask(CreateNewBlockingIncrementingTask());
@@ -228,7 +228,7 @@ TEST_F(LinuxDynamicThreadPoolTest, TwoActiveTasks) {
EXPECT_EQ(2, counter_);
}
-TEST_F(LinuxDynamicThreadPoolTest, Complex) {
+TEST_F(PosixDynamicThreadPoolTest, Complex) {
// Add two non blocking tasks and wait for them to finish.
pool_->PostTask(CreateNewIncrementingTask());