diff options
author | Kristian Monsen <kristianm@google.com> | 2011-06-28 21:49:31 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-07-08 17:55:00 +0100 |
commit | ddb351dbec246cf1fab5ec20d2d5520909041de1 (patch) | |
tree | 158e3fb57bdcac07c7f1e767fde3c70687c9fbb1 /base | |
parent | 6b92e04f5f151c896e3088e86f70db7081009308 (diff) | |
download | external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.zip external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.tar.gz external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.tar.bz2 |
Merge Chromium at r12.0.742.93: Initial merge by git
Change-Id: Ic5ee2fec31358bbee305f7e915442377bfa6cda6
Diffstat (limited to 'base')
349 files changed, 6816 insertions, 10626 deletions
diff --git a/base/OWNERS b/base/OWNERS new file mode 100644 index 0000000..41dd3c9 --- /dev/null +++ b/base/OWNERS @@ -0,0 +1,6 @@ +set noparent +mark@chromium.org +darin@chromium.org +brettw@chromium.org +evan@chromium.org +willchan@chromium.org diff --git a/base/allocator/allocator_shim.cc b/base/allocator/allocator_shim.cc index f11164c..97946e7 100644 --- a/base/allocator/allocator_shim.cc +++ b/base/allocator/allocator_shim.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/base/at_exit.cc b/base/at_exit.cc index e6618a0..e467c5d 100644 --- a/base/at_exit.cc +++ b/base/at_exit.cc @@ -1,8 +1,12 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/at_exit.h" + +#include <stddef.h> +#include <ostream> + #include "base/logging.h" namespace base { diff --git a/base/at_exit.h b/base/at_exit.h index 15dcfc8..06214d1 100644 --- a/base/at_exit.h +++ b/base/at_exit.h @@ -8,6 +8,7 @@ #include <stack> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/synchronization/lock.h" @@ -27,7 +28,7 @@ namespace base { // When the exit_manager object goes out of scope, all the registered // callbacks and singleton destructors will be called. -class AtExitManager { +class BASE_API AtExitManager { public: typedef void (*AtExitCallbackType)(void*); diff --git a/base/atomic_ref_count.h b/base/atomic_ref_count.h index dff4b1f..985c42c 100644 --- a/base/atomic_ref_count.h +++ b/base/atomic_ref_count.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This is a low level implementation of atomic semantics for reference -// counting. Please use base/ref_counted.h directly instead. +// counting. Please use base/memory/ref_counted.h directly instead. // // The implementation includes annotations to avoid some false positives // when using data race detection tools. diff --git a/base/atomicops.h b/base/atomicops.h index 445696b..5b2b9dd 100644 --- a/base/atomicops.h +++ b/base/atomicops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -30,7 +30,7 @@ #pragma once #include "base/basictypes.h" -#include "base/port.h" +#include "build/build_config.h" namespace base { namespace subtle { @@ -145,4 +145,10 @@ Atomic64 Release_Load(volatile const Atomic64* ptr); #error "Atomic operations are not supported on your platform" #endif +// On some platforms we need additional declarations to make +// AtomicWord compatible with our other Atomic* types. +#if defined(OS_MACOSX) || defined(OS_OPENBSD) +#include "base/atomicops_internals_atomicword_compat.h" +#endif + #endif // BASE_ATOMICOPS_H_ diff --git a/base/atomicops_internals_atomicword_compat.h b/base/atomicops_internals_atomicword_compat.h new file mode 100644 index 0000000..8382fe1 --- /dev/null +++ b/base/atomicops_internals_atomicword_compat.h @@ -0,0 +1,101 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is an internal atomic implementation, use base/atomicops.h instead. + +#ifndef BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ +#define BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ +#pragma once + +// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32, +// which in turn means int. On some LP32 platforms, intptr_t is an int, but +// on others, it's a long. When AtomicWord and Atomic32 are based on different +// fundamental types, their pointers are incompatible. +// +// This file defines function overloads to allow both AtomicWord and Atomic32 +// data to be used with this interface. +// +// On LP64 platforms, AtomicWord and Atomic64 are both always long, +// so this problem doesn't occur. + +#if !defined(ARCH_CPU_64_BITS) + +namespace base { +namespace subtle { + +inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return NoBarrier_CompareAndSwap( + reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value); +} + +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return NoBarrier_AtomicExchange( + reinterpret_cast<volatile Atomic32*>(ptr), new_value); +} + +inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return NoBarrier_AtomicIncrement( + reinterpret_cast<volatile Atomic32*>(ptr), increment); +} + +inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return Barrier_AtomicIncrement( + reinterpret_cast<volatile Atomic32*>(ptr), increment); +} + +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Acquire_CompareAndSwap( + reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value); +} + +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Release_CompareAndSwap( + reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value); +} + +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { + NoBarrier_Store( + reinterpret_cast<volatile Atomic32*>(ptr), value); +} + +inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Acquire_Store( + reinterpret_cast<volatile Atomic32*>(ptr), value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Release_Store( + reinterpret_cast<volatile Atomic32*>(ptr), value); +} + +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { + return NoBarrier_Load( + reinterpret_cast<volatile const Atomic32*>(ptr)); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return base::subtle::Acquire_Load( + reinterpret_cast<volatile const Atomic32*>(ptr)); +} + +inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { + return base::subtle::Release_Load( + reinterpret_cast<volatile const Atomic32*>(ptr)); +} + +} // namespace base::subtle +} // namespace base + +#endif // !defined(ARCH_CPU_64_BITS) + +#endif // BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ diff --git a/base/atomicops_internals_x86_macosx.h b/base/atomicops_internals_x86_macosx.h index 29e58e3..4b7cec8 100644 --- a/base/atomicops_internals_x86_macosx.h +++ b/base/atomicops_internals_x86_macosx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -192,89 +192,6 @@ inline Atomic64 Release_Load(volatile const Atomic64 *ptr) { #endif // defined(__LP64__) -// MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different -// on the Mac, even when they are the same size. We need to explicitly cast -// from AtomicWord to Atomic32 to implement the AtomicWord interface. -// When in 64-bit mode, AtomicWord is the same as Atomic64, so we need not -// add duplicate definitions. -#ifndef __LP64__ -#define AtomicWordCastType Atomic32 - -inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, - AtomicWord old_value, - AtomicWord new_value) { - return NoBarrier_CompareAndSwap( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), - old_value, new_value); -} - -inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, - AtomicWord new_value) { - return NoBarrier_AtomicExchange( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value); -} - -inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, - AtomicWord increment) { - return NoBarrier_AtomicIncrement( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment); -} - -inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, - AtomicWord increment) { - return Barrier_AtomicIncrement( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment); -} - -inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, - AtomicWord old_value, - AtomicWord new_value) { - return base::subtle::Acquire_CompareAndSwap( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), - old_value, new_value); -} - -inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, - AtomicWord old_value, - AtomicWord new_value) { - return base::subtle::Release_CompareAndSwap( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), - old_value, new_value); -} - -inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { - NoBarrier_Store( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), value); -} - -inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { - return base::subtle::Acquire_Store( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), value); -} - -inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { - return base::subtle::Release_Store( - reinterpret_cast<volatile AtomicWordCastType*>(ptr), value); -} - -inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { - return NoBarrier_Load( - reinterpret_cast<volatile const AtomicWordCastType*>(ptr)); -} - -inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { - return base::subtle::Acquire_Load( - reinterpret_cast<volatile const AtomicWordCastType*>(ptr)); -} - -inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { - return base::subtle::Release_Load( - reinterpret_cast<volatile const AtomicWordCastType*>(ptr)); -} - -#undef AtomicWordCastType -#endif - } // namespace base::subtle } // namespace base diff --git a/base/atomicops_unittest.cc b/base/atomicops_unittest.cc index 5053b0b..d73a098 100644 --- a/base/atomicops_unittest.cc +++ b/base/atomicops_unittest.cc @@ -1,8 +1,12 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/atomicops.h" + +#include <string.h> + +#include "base/port.h" #include "testing/gtest/include/gtest/gtest.h" template <class AtomicType> diff --git a/base/base.gyp b/base/base.gyp index 525d316..37b197d 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -54,6 +54,48 @@ ], }, { + # This is the subset of files from base that should not be used with a + # dynamic library. + 'target_name': 'base_static', + 'type': '<(library)', + 'sources': [ + 'base_switches.cc', + 'base_switches.h', + 'win/pe_image.cc', + 'win/pe_image.h', + ], + 'include_dirs': [ + '..', + ], + }, + { + # TODO(rvargas): Remove this when gyp finally supports a clean model. + # See bug 36232. + 'target_name': 'base_static_win64', + 'type': '<(library)', + 'sources': [ + 'base_switches.cc', + 'base_switches.h', + 'win/pe_image.cc', + 'win/pe_image.h', + ], + 'include_dirs': [ + '..', + ], + 'configurations': { + 'Common_Base': { + 'msvs_target_platform': 'x64', + }, + }, + 'defines': [ + 'NACL_WIN64', + ], + # TODO(rvargas): Bug 78117. Remove this. + 'msvs_disabled_warnings': [ + 4244, + ], + }, + { 'target_name': 'base_unittests', 'type': 'executable', 'msvs_guid': '27A30967-4BBA-48D1-8522-CDE95F7B1CEC', @@ -70,13 +112,6 @@ 'callback_unittest.cc', 'command_line_unittest.cc', 'cpu_unittest.cc', - 'crypto/encryptor_unittest.cc', - 'crypto/rsa_private_key_unittest.cc', - 'crypto/rsa_private_key_nss_unittest.cc', - 'crypto/secure_hash_unittest.cc', - 'crypto/signature_creator_unittest.cc', - 'crypto/signature_verifier_unittest.cc', - 'crypto/symmetric_key_unittest.cc', 'debug/leak_tracker_unittest.cc', 'debug/stack_trace_unittest.cc', 'debug/trace_event_win_unittest.cc', @@ -87,7 +122,6 @@ 'file_util_unittest.cc', 'file_version_info_unittest.cc', 'gmock_unittest.cc', - 'hmac_unittest.cc', 'id_map_unittest.cc', 'i18n/break_iterator_unittest.cc', 'i18n/char_iterator_unittest.cc', @@ -99,9 +133,16 @@ 'json/string_escape_unittest.cc', 'lazy_instance_unittest.cc', 'linked_list_unittest.cc', - 'linked_ptr_unittest.cc', 'logging_unittest.cc', 'mac/mac_util_unittest.mm', + 'memory/linked_ptr_unittest.cc', + 'memory/ref_counted_unittest.cc', + 'memory/scoped_native_library_unittest.cc', + 'memory/scoped_ptr_unittest.cc', + 'memory/scoped_temp_dir_unittest.cc', + 'memory/scoped_vector_unittest.cc', + 'memory/singleton_unittest.cc', + 'memory/weak_ptr_unittest.cc', 'message_loop_proxy_impl_unittest.cc', 'message_loop_unittest.cc', 'message_pump_glib_unittest.cc', @@ -117,14 +158,8 @@ 'process_util_unittest_mac.h', 'process_util_unittest_mac.mm', 'rand_util_unittest.cc', - 'ref_counted_unittest.cc', - 'scoped_native_library_unittest.cc', - 'scoped_ptr_unittest.cc', - 'scoped_temp_dir_unittest.cc', 'sha1_unittest.cc', - 'sha2_unittest.cc', 'shared_memory_unittest.cc', - 'singleton_unittest.cc', 'stack_container_unittest.cc', 'string16_unittest.cc', 'string_number_conversions_unittest.cc', @@ -167,7 +202,6 @@ 'values_unittest.cc', 'version_unittest.cc', 'vlog_unittest.cc', - 'weak_ptr_unittest.cc', 'win/event_trace_consumer_unittest.cc', 'win/event_trace_controller_unittest.cc', 'win/event_trace_provider_unittest.cc', @@ -179,10 +213,12 @@ 'win/scoped_comptr_unittest.cc', 'win/scoped_variant_unittest.cc', 'win/win_util_unittest.cc', + 'win/wrapped_window_proc_unittest.cc', ], 'dependencies': [ 'base', 'base_i18n', + 'base_static', 'test_support_base', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', @@ -211,7 +247,6 @@ }, { # OS != "linux" and OS != "freebsd" and OS != "openbsd" and OS != "solaris" 'sources!': [ 'message_pump_glib_unittest.cc', - 'crypto/rsa_private_key_nss_unittest.cc', ] }], # This is needed to trigger the dll copy step on windows. @@ -236,11 +271,6 @@ 'win_util_unittest.cc', ], }], - [ 'use_openssl==1', { - 'sources!': [ - 'crypto/rsa_private_key_nss_unittest.cc', - ], - }], ], }, { diff --git a/base/base.gypi b/base/base.gypi index ef1d8d8..8e49dd5 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -26,6 +26,7 @@ 'atomicops.h', 'atomicops_internals_x86_gcc.cc', 'atomicops_internals_x86_msvc.h', + 'base_api.h', 'base_paths.cc', 'base_paths.h', 'base_paths_mac.h', @@ -33,8 +34,6 @@ 'base_paths_linux.cc', 'base_paths_win.cc', 'base_paths_win.h', - 'base_switches.cc', - 'base_switches.h', 'basictypes.h', 'bind.h', 'bind_helpers.h', @@ -89,6 +88,11 @@ 'file_version_info_mac.mm', 'file_version_info_win.cc', 'file_version_info_win.h', + 'files/file_path_watcher.cc', + 'files/file_path_watcher.h', + 'files/file_path_watcher_linux.cc', + 'files/file_path_watcher_mac.cc', + 'files/file_path_watcher_win.cc', 'fix_wp64.h', 'float_util.h', 'foundation_utils_mac.h', @@ -106,13 +110,13 @@ 'lazy_instance.cc', 'lazy_instance.h', 'linked_list.h', - 'linked_ptr.h', 'logging.cc', 'logging.h', 'logging_win.cc', + 'logging_win.h', 'mac/cocoa_protocols.h', - 'mac/foundation_util.h', - 'mac/foundation_util.mm', + 'mac/foundation_util.h', + 'mac/foundation_util.mm', 'mac/mac_util.h', 'mac/mac_util.mm', 'mac/os_crash_dumps.cc', @@ -123,8 +127,27 @@ 'mac/scoped_nsautorelease_pool.mm', 'mach_ipc_mac.h', 'mach_ipc_mac.mm', - 'memory_debug.cc', - 'memory_debug.h', + 'memory/linked_ptr.h', + 'memory/memory_debug.cc', + 'memory/memory_debug.h', + 'memory/raw_scoped_refptr_mismatch_checker.h', + 'memory/ref_counted.cc', + 'memory/ref_counted.h', + 'memory/ref_counted_memory.cc', + 'memory/ref_counted_memory.h', + 'memory/scoped_callback_factory.h', + 'memory/scoped_handle.h', + 'memory/scoped_native_library.cc', + 'memory/scoped_native_library.h', + 'memory/scoped_nsobject.h', + 'memory/scoped_open_process.h', + 'memory/scoped_ptr.h', + 'memory/scoped_temp_dir.cc', + 'memory/scoped_temp_dir.h', + 'memory/scoped_vector.h', + 'memory/singleton.h', + 'memory/weak_ptr.cc', + 'memory/weak_ptr.h', 'message_loop.cc', 'message_loop.h', 'message_loop_proxy.cc', @@ -176,32 +199,17 @@ 'rand_util.h', 'rand_util_posix.cc', 'rand_util_win.cc', - 'raw_scoped_refptr_mismatch_checker.h', - 'ref_counted.cc', - 'ref_counted.h', - 'ref_counted_memory.cc', - 'ref_counted_memory.h', 'resource_util.cc', 'resource_util.h', 'safe_strerror_posix.cc', 'safe_strerror_posix.h', - 'scoped_callback_factory.h', - 'scoped_handle.h', - 'scoped_native_library.cc', - 'scoped_native_library.h', - 'scoped_nsobject.h', - 'scoped_open_process.h', 'scoped_ptr.h', - 'scoped_temp_dir.cc', - 'scoped_temp_dir.h', - 'scoped_vector.h', 'sha1.h', 'sha1_portable.cc', 'sha1_win.cc', 'shared_memory.h', 'shared_memory_posix.cc', 'shared_memory_win.cc', - 'singleton.h', 'spin_wait.h', 'stack_container.h', 'stl_util-inl.h', @@ -299,23 +307,21 @@ 'utf_string_conversions.h', 'values.cc', 'values.h', + 'value_conversions.cc', + 'value_conversions.h', 'version.cc', 'version.h', 'vlog.cc', 'vlog.h', - 'weak_ptr.cc', - 'weak_ptr.h', - 'win/i18n.cc', - 'win/i18n.h', - 'win/object_watcher.cc', - 'win/object_watcher.h', - 'win/pe_image.cc', 'win/event_trace_consumer.h', 'win/event_trace_controller.cc', 'win/event_trace_controller.h', 'win/event_trace_provider.cc', 'win/event_trace_provider.h', - 'win/pe_image.h', + 'win/i18n.cc', + 'win/i18n.h', + 'win/object_watcher.cc', + 'win/object_watcher.h', 'win/registry.cc', 'win/registry.h', 'win/scoped_bstr.cc', @@ -331,6 +337,8 @@ 'win/win_util.h', 'win/windows_version.cc', 'win/windows_version.h', + 'win/wrapped_window_proc.cc', + 'win/wrapped_window_proc.h', 'nix/xdg_util.h', 'nix/xdg_util.cc', ], @@ -398,6 +406,14 @@ 'debug/trace_event.cc', ], },], + ['OS=="freebsd" or OS=="openbsd"', { + 'sources!': [ + 'base/files/file_path_watcher_linux.cc', + ], + 'sources': [ + 'base/files/file_path_watcher_stub.cc', + ], + }], ], }], ], @@ -411,6 +427,7 @@ 'base_target': 1, }, 'dependencies': [ + 'base_static', '../third_party/modp_b64/modp_b64.gyp:modp_b64', 'third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', ], @@ -439,16 +456,6 @@ }, }, ], - [ 'use_openssl==1', { - 'dependencies': [ - '../third_party/openssl/openssl.gyp:openssl', - ], - }, { # use_openssl==0 - 'dependencies': [ - '../build/linux/system.gyp:nss', - ], - } - ], ], 'dependencies': [ 'symbolize', @@ -502,112 +509,25 @@ '$(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', - ], - },], [ 'OS != "win"', { 'dependencies': ['../third_party/libevent/libevent.gyp:libevent'], 'sources!': [ 'third_party/purify/pure_api.c', 'base_drag_source.cc', 'base_drop_target.cc', - 'crypto/capi_util.h', - 'crypto/capi_util.cc', 'event_recorder.cc', 'file_version_info.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/secure_hash_default.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/secure_hash_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/crypto_module_blocking_password_delegate.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/secure_hash.h', - 'crypto/secure_hash_default.cc', - 'crypto/secure_hash_openssl.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', @@ -620,11 +540,6 @@ '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', @@ -640,13 +555,6 @@ 'message_pump_mac.mm', 'metrics/field_trial.cc', 'metrics/field_trial.h', - 'nss_util.cc', - 'nss_util.h', - 'openssl_util.cc', - 'openssl_util.h', - 'sha2.cc', - 'sha2.h', - 'sha2_openssl.cc', 'string16.cc', 'string16.h', 'sync_socket.h', @@ -668,6 +576,7 @@ 'base_target': 1, }, 'dependencies': [ + 'base_static_win64', 'third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64', ], # TODO(gregoryd): direct_dependent_settings should be shared with the diff --git a/base/base64.h b/base/base64.h index 39cebfb..294fb83 100644 --- a/base/base64.h +++ b/base/base64.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,15 +8,17 @@ #include <string> +#include "base/base_api.h" + namespace base { // Encodes the input string in base64. Returns true if successful and false // otherwise. The output string is only modified if successful. -bool Base64Encode(const std::string& input, std::string* output); +BASE_API bool Base64Encode(const std::string& input, std::string* output); // Decodes the base64 input string. Returns true if successful and false // otherwise. The output string is only modified if successful. -bool Base64Decode(const std::string& input, std::string* output); +BASE_API bool Base64Decode(const std::string& input, std::string* output); } // namespace base diff --git a/base/base_api.h b/base/base_api.h new file mode 100644 index 0000000..83b4bdf --- /dev/null +++ b/base/base_api.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_BASE_API_H_ +#define BASE_BASE_API_H_ +#pragma once + +#if defined(WIN32) && defined(BASE_DLL) +#if defined(BASE_IMPLEMENTATION) +#define BASE_API __declspec(dllexport) +#else +#define BASE_API __declspec(dllimport) +#endif // defined(BASE_IMPLEMENTATION) +#else +#define BASE_API +#endif + +#endif // BASE_BASE_API_H_ diff --git a/base/base_paths.h b/base/base_paths.h index 72cff15..3c3c8ed 100644 --- a/base/base_paths.h +++ b/base/base_paths.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,8 @@ // This file declares path keys for the base module. These can be used with // the PathService to access various special directories and files. -#include "base/basictypes.h" +#include "build/build_config.h" + #if defined(OS_WIN) #include "base/base_paths_win.h" #elif defined(OS_MACOSX) diff --git a/base/base_paths_linux.cc b/base/base_paths_linux.cc index ca8c757..a5fdb12 100644 --- a/base/base_paths_linux.cc +++ b/base/base_paths_linux.cc @@ -1,24 +1,26 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/base_paths.h" -#include <unistd.h> -#if defined(OS_FREEBSD) -#include <sys/param.h> -#include <sys/sysctl.h> -#endif +#include <ostream> +#include <string> +#include "build/build_config.h" #include "base/environment.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/path_service.h" -#include "base/scoped_ptr.h" -#include "base/sys_string_conversions.h" #include "base/nix/xdg_util.h" +#if defined(OS_FREEBSD) +#include <sys/param.h> +#include <sys/sysctl.h> +#endif + namespace base { #if defined(OS_LINUX) diff --git a/base/base_paths_mac.mm b/base/base_paths_mac.mm index 1210834..ec1398b 100644 --- a/base/base_paths_mac.mm +++ b/base/base_paths_mac.mm @@ -53,19 +53,20 @@ bool PathProviderMac(int key, FilePath* result) { return base::mac::GetUserDirectory(NSApplicationSupportDirectory, result); case base::DIR_SOURCE_ROOT: { // Go through PathService to catch overrides. - if (PathService::Get(base::FILE_EXE, result)) { - // Start with the executable's directory. - *result = result->DirName(); - if (base::mac::AmIBundled()) { - // The bundled app executables (Chromium, TestShell, etc) live five - // levels down, eg: - // src/xcodebuild/{Debug|Release}/Chromium.app/Contents/MacOS/Chromium - *result = result->DirName().DirName().DirName().DirName().DirName(); - } else { - // Unit tests execute two levels deep from the source root, eg: - // src/xcodebuild/{Debug|Release}/base_unittests - *result = result->DirName().DirName(); - } + if (!PathService::Get(base::FILE_EXE, result)) + return false; + + // Start with the executable's directory. + *result = result->DirName(); + if (base::mac::AmIBundled()) { + // The bundled app executables (Chromium, TestShell, etc) live five + // levels down, eg: + // src/xcodebuild/{Debug|Release}/Chromium.app/Contents/MacOS/Chromium + *result = result->DirName().DirName().DirName().DirName().DirName(); + } else { + // Unit tests execute two levels deep from the source root, eg: + // src/xcodebuild/{Debug|Release}/base_unittests + *result = result->DirName().DirName(); } return true; } diff --git a/base/basictypes.h b/base/basictypes.h index 74c0460..1188d8d 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -27,9 +27,12 @@ typedef short int16; typedef int int32; #endif -// The NSPR system headers define 64-bit as |long| when possible. In order to -// not have typedef mismatches, we do the same on LP64. -#if __LP64__ +// The NSPR system headers define 64-bit as |long| when possible, except on +// Mac OS X. In order to not have typedef mismatches, we do the same on LP64. +// +// On Mac OS X, |long long| is used for 64-bit types for compatibility with +// <inttypes.h> format macros even in the LP64 model. +#if defined(__LP64__) && !defined(OS_MACOSX) typedef long int64; #else typedef long long int64; @@ -51,7 +54,7 @@ typedef unsigned int uint32; #endif // See the comment above about NSPR and 64-bit. -#if __LP64__ +#if defined(__LP64__) && !defined(OS_MACOSX) typedef unsigned long uint64; #else typedef unsigned long long uint64; diff --git a/base/bind_helpers.h b/base/bind_helpers.h index c1ca3d7..3293dbb 100644 --- a/base/bind_helpers.h +++ b/base/bind_helpers.h @@ -133,8 +133,17 @@ class SupportsAddRefAndRelease { void Release(); }; +// MSVC warns when you try to use Base if T has a private destructor, the +// common pattern for refcounted types. It does this even though no attempt to +// instantiate Base is made. We disable the warning for this definition. +#if defined(OS_WIN) +#pragma warning(disable:4624) +#endif struct Base : public T, public BaseMixin { }; +#if defined(OS_WIN) +#pragma warning(default:4624) +#endif template <void(BaseMixin::*)(void)> struct Helper {}; @@ -161,7 +170,11 @@ struct UnsafeBindtoRefCountedArgHelper<true, T> }; template <typename T> -struct UnsafeBindtoRefCountedArg +struct UnsafeBindtoRefCountedArg : false_type { +}; + +template <typename T> +struct UnsafeBindtoRefCountedArg<T*> : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { }; @@ -233,43 +246,6 @@ struct MaybeRefcount<base::true_type, const T*> { static void Release(const T* o) { o->Release(); } }; - -// This is a typetraits object that's used to convert an argument type into a -// type suitable for storage. In particular, it strips off references, and -// converts arrays to pointers. -// -// This array type becomes an issue because we are passing bound parameters by -// const reference. In this case, we end up passing an actual array type in the -// initializer list which C++ does not allow. This will break passing of -// C-string literals. -template <typename T> -struct BindType { - typedef T StorageType; -}; - -// This should almost be impossible to trigger unless someone manually -// specifies type of the bind parameters. However, in case they do, -// this will guard against us accidentally storing a reference parameter. -template <typename T> -struct BindType<T&> { - typedef T StorageType; -}; - -// Note that for array types, we implicitly add a const in the conversion. This -// means that it is not possible to bind array arguments to functions that take -// a non-const pointer. Trying to specialize the template based on a "const -// T[n]" does not seem to match correctly, so we are stuck with this -// restriction. -template <typename T, size_t n> -struct BindType<T[n]> { - typedef const T* StorageType; -}; - -template <typename T> -struct BindType<T[]> { - typedef const T* StorageType; -}; - } // namespace internal template <typename T> diff --git a/base/bind_internal.h b/base/bind_internal.h index bb5f46f..606e2b0 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h @@ -3,6 +3,7 @@ // DO NOT EDIT BY HAND!!! + // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -73,6 +74,7 @@ template <typename R> struct FunctionTraits<R(*)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + }; // Method: Arity 0. @@ -80,6 +82,10 @@ template <typename R, typename T> struct FunctionTraits<R(T::*)()> { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + }; // Const Method: Arity 0. @@ -87,6 +93,10 @@ template <typename R, typename T> struct FunctionTraits<R(T::*)() const> { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + }; // Function: Arity 1. @@ -94,6 +104,9 @@ template <typename R, typename X1> struct FunctionTraits<R(*)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + }; // Method: Arity 1. @@ -101,6 +114,11 @@ template <typename R, typename T, typename X1> struct FunctionTraits<R(T::*)(X1)> { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + }; // Const Method: Arity 1. @@ -108,6 +126,11 @@ template <typename R, typename T, typename X1> struct FunctionTraits<R(T::*)(X1) const> { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + }; // Function: Arity 2. @@ -115,6 +138,10 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(*)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + }; // Method: Arity 2. @@ -122,6 +149,12 @@ template <typename R, typename T, typename X1, typename X2> struct FunctionTraits<R(T::*)(X1, X2)> { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + }; // Const Method: Arity 2. @@ -129,6 +162,12 @@ template <typename R, typename T, typename X1, typename X2> struct FunctionTraits<R(T::*)(X1, X2) const> { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + }; // Function: Arity 3. @@ -136,6 +175,11 @@ template <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(*)(X1, X2, X3)> { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + }; // Method: Arity 3. @@ -143,6 +187,13 @@ template <typename R, typename T, typename X1, typename X2, typename X3> struct FunctionTraits<R(T::*)(X1, X2, X3)> { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + }; // Const Method: Arity 3. @@ -150,6 +201,13 @@ template <typename R, typename T, typename X1, typename X2, typename X3> struct FunctionTraits<R(T::*)(X1, X2, X3) const> { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + }; // Function: Arity 4. @@ -157,6 +215,12 @@ template <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(*)(X1, X2, X3, X4)> { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + }; // Method: Arity 4. @@ -165,6 +229,14 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + }; // Const Method: Arity 4. @@ -173,6 +245,14 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + }; // Function: Arity 5. @@ -181,6 +261,13 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(*)(X1, X2, X3, X4, X5)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + }; // Method: Arity 5. @@ -189,6 +276,15 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + }; // Const Method: Arity 5. @@ -197,6 +293,15 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + }; // Function: Arity 6. @@ -205,6 +310,14 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(*)(X1, X2, X3, X4, X5, X6)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + typedef X6 B6; + }; // Method: Arity 6. @@ -213,6 +326,16 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6)> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + typedef X6 B7; + }; // Const Method: Arity 6. @@ -221,6 +344,16 @@ template <typename R, typename T, typename X1, typename X2, typename X3, struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6) const> { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + typedef X1 B2; + typedef X2 B3; + typedef X3 B4; + typedef X4 B5; + typedef X5 B6; + typedef X6 B7; + }; // InvokerN<> @@ -258,11 +391,8 @@ struct Invoker0<StorageType, R(*)()> { // Function: Arity 1 -> 1. template <typename StorageType, typename R,typename X1> struct Invoker0<StorageType, R(*)(X1)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1); } @@ -271,12 +401,9 @@ struct Invoker0<StorageType, R(*)(X1)> { // Function: Arity 2 -> 2. template <typename StorageType, typename R,typename X1, typename X2> struct Invoker0<StorageType, R(*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1, x2); } @@ -286,14 +413,10 @@ struct Invoker0<StorageType, R(*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker0<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1, x2, x3); } @@ -303,15 +426,11 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1, x2, x3, x4); } @@ -321,16 +440,12 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1, x2, x3, x4, x5); } @@ -340,17 +455,13 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4, const X5& x5, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(x1, x2, x3, x4, x5, x6); } @@ -362,10 +473,6 @@ struct Invoker1; // Function: Arity 1 -> 0. template <typename StorageType, typename R,typename X1> struct Invoker1<StorageType, R(*)(X1)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_)); @@ -384,12 +491,8 @@ struct Invoker1<StorageType, R(T::*)()> { // Function: Arity 2 -> 1. template <typename StorageType, typename R,typename X1, typename X2> struct Invoker1<StorageType, R(*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2); } @@ -398,11 +501,8 @@ struct Invoker1<StorageType, R(*)(X1, X2)> { // Method: Arity 1 -> 1. template <typename StorageType, typename R, typename T, typename X1> struct Invoker1<StorageType, R(T::*)(X1)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(x1); } @@ -412,13 +512,9 @@ struct Invoker1<StorageType, R(T::*)(X1)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker1<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2, x3); } @@ -428,12 +524,9 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R, typename T, typename X1, typename X2> struct Invoker1<StorageType, R(T::*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2); } @@ -443,15 +536,10 @@ struct Invoker1<StorageType, R(T::*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4); } @@ -461,14 +549,10 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3); } @@ -478,16 +562,11 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5); } @@ -497,15 +576,11 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4); } @@ -515,17 +590,12 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4, const X5& x5, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5, x6); } @@ -535,16 +605,12 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2, - const X3& x3, const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4, x5); } @@ -556,11 +622,6 @@ struct Invoker2; // Function: Arity 2 -> 0. template <typename StorageType, typename R,typename X1, typename X2> struct Invoker2<StorageType, R(*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_)); @@ -570,10 +631,6 @@ struct Invoker2<StorageType, R(*)(X1, X2)> { // Method: Arity 1 -> 0. template <typename StorageType, typename R, typename T, typename X1> struct Invoker2<StorageType, R(T::*)(X1)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_)); @@ -584,13 +641,8 @@ struct Invoker2<StorageType, R(T::*)(X1)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker2<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3); } @@ -600,12 +652,8 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R, typename T, typename X1, typename X2> struct Invoker2<StorageType, R(T::*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2); } @@ -615,14 +663,9 @@ struct Invoker2<StorageType, R(T::*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4); } @@ -632,13 +675,9 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3); } @@ -648,16 +687,10 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4, - const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5); } @@ -667,15 +700,10 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4); @@ -686,17 +714,11 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4, - const X5& x5, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5, x6); @@ -707,16 +729,11 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3, - const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4, x5); @@ -730,12 +747,6 @@ struct Invoker3; template <typename StorageType, typename R,typename X1, typename X2, typename X3> struct Invoker3<StorageType, R(*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -747,11 +758,6 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3)> { template <typename StorageType, typename R, typename T, typename X1, typename X2> struct Invoker3<StorageType, R(T::*)(X1, X2)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -763,14 +769,8 @@ struct Invoker3<StorageType, R(T::*)(X1, X2)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), x4); @@ -781,13 +781,8 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3); @@ -798,15 +793,9 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), x4, x5); @@ -817,14 +806,9 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, x4); @@ -835,17 +819,10 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5, - const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), x4, x5, x6); @@ -856,16 +833,10 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4, - const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, x4, x5); @@ -879,13 +850,6 @@ struct Invoker4; template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -897,12 +861,6 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -914,15 +872,8 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5); @@ -933,14 +884,8 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4); @@ -951,16 +896,9 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X5& x5, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5, x6); @@ -971,15 +909,9 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4, x5); @@ -993,14 +925,6 @@ struct Invoker5; template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -1012,13 +936,6 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -1030,16 +947,8 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X6& x6) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x6); @@ -1050,15 +959,8 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - - static R DoInvoke(InvokerStorageBase* base, const X5& x5) { + static R DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5); @@ -1072,15 +974,6 @@ struct Invoker6; template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value || - is_non_const_reference<X6>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -1093,14 +986,6 @@ struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - COMPILE_ASSERT( - !( is_non_const_reference<X1>::value || - is_non_const_reference<X2>::value || - is_non_const_reference<X3>::value || - is_non_const_reference<X4>::value || - is_non_const_reference<X5>::value ), - do_not_bind_functions_with_nonconst_ref); - static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -1133,6 +1018,7 @@ class InvokerStorage0 : public InvokerStorageBase { typedef typename TargetTraits::IsMethod IsMethod; + InvokerStorage0(Sig f) : f_(f) { } @@ -1149,6 +1035,7 @@ class InvokerStorage1 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker1<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also // disallow binding of an array as the method's target object. @@ -1158,9 +1045,18 @@ class InvokerStorage1 : public InvokerStorageBase { COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, first_bound_argument_to_method_cannot_be_array); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage1(Sig f, const P1& p1) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1169,7 +1065,7 @@ class InvokerStorage1 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; + typename ParamTraits<P1>::StorageType p1_; }; template <typename Sig, typename P1, typename P2> @@ -1179,6 +1075,7 @@ class InvokerStorage2 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker2<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also // disallow binding of an array as the method's target object. @@ -1190,10 +1087,20 @@ class InvokerStorage2 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value, p2_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage2(Sig f, const P1& p1, const P2& p2) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1202,8 +1109,8 @@ class InvokerStorage2 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; }; template <typename Sig, typename P1, typename P2, typename P3> @@ -1213,6 +1120,7 @@ class InvokerStorage3 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker3<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also // disallow binding of an array as the method's target object. @@ -1226,11 +1134,22 @@ class InvokerStorage3 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value, p3_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage3(Sig f, const P1& p1, const P2& p2, const P3& p3) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1239,9 +1158,9 @@ class InvokerStorage3 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; }; template <typename Sig, typename P1, typename P2, typename P3, typename P4> @@ -1251,6 +1170,7 @@ class InvokerStorage4 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker4<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also // disallow binding of an array as the method's target object. @@ -1266,12 +1186,24 @@ class InvokerStorage4 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value, p4_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value || + is_non_const_reference<typename TargetTraits::B4>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage4(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)), - p4_(static_cast<typename BindType<P4>::StorageType>(p4)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), + p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1280,10 +1212,10 @@ class InvokerStorage4 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; - typename BindType<P4>::StorageType p4_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; + typename ParamTraits<P4>::StorageType p4_; }; template <typename Sig, typename P1, typename P2, typename P3, typename P4, @@ -1294,6 +1226,7 @@ class InvokerStorage5 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker5<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also // disallow binding of an array as the method's target object. @@ -1311,14 +1244,27 @@ class InvokerStorage5 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value, p5_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value || + is_non_const_reference<typename TargetTraits::B4>::value || + is_non_const_reference<typename TargetTraits::B5>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage5(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)), - p4_(static_cast<typename BindType<P4>::StorageType>(p4)), - p5_(static_cast<typename BindType<P5>::StorageType>(p5)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), + p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)), + p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1327,11 +1273,11 @@ class InvokerStorage5 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; - typename BindType<P4>::StorageType p4_; - typename BindType<P5>::StorageType p5_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; + typename ParamTraits<P4>::StorageType p4_; + typename ParamTraits<P5>::StorageType p5_; }; template <typename Sig, typename P1, typename P2, typename P3, typename P4, @@ -1342,6 +1288,7 @@ class InvokerStorage6 : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker6<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also // disallow binding of an array as the method's target object. @@ -1361,15 +1308,29 @@ class InvokerStorage6 : public InvokerStorageBase { COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P6>::value, p6_is_refcounted_type_and_needs_scoped_refptr); + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !( is_non_const_reference<typename TargetTraits::B1>::value || + is_non_const_reference<typename TargetTraits::B2>::value || + is_non_const_reference<typename TargetTraits::B3>::value || + is_non_const_reference<typename TargetTraits::B4>::value || + is_non_const_reference<typename TargetTraits::B5>::value || + is_non_const_reference<typename TargetTraits::B6>::value ), + do_not_bind_functions_with_nonconst_ref); + InvokerStorage6(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) - : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)), - p2_(static_cast<typename BindType<P2>::StorageType>(p2)), - p3_(static_cast<typename BindType<P3>::StorageType>(p3)), - p4_(static_cast<typename BindType<P4>::StorageType>(p4)), - p5_(static_cast<typename BindType<P5>::StorageType>(p5)), - p6_(static_cast<typename BindType<P6>::StorageType>(p6)) { + : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), + p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), + p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), + p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)), + p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)), + p6_(static_cast<typename ParamTraits<P6>::StorageType>(p6)) { MaybeRefcount<IsMethod, P1>::AddRef(p1_); } @@ -1378,12 +1339,12 @@ class InvokerStorage6 : public InvokerStorageBase { } Sig f_; - typename BindType<P1>::StorageType p1_; - typename BindType<P2>::StorageType p2_; - typename BindType<P3>::StorageType p3_; - typename BindType<P4>::StorageType p4_; - typename BindType<P5>::StorageType p5_; - typename BindType<P6>::StorageType p6_; + typename ParamTraits<P1>::StorageType p1_; + typename ParamTraits<P2>::StorageType p2_; + typename ParamTraits<P3>::StorageType p3_; + typename ParamTraits<P4>::StorageType p4_; + typename ParamTraits<P5>::StorageType p5_; + typename ParamTraits<P6>::StorageType p6_; }; } // namespace internal diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump index 84fb2ef..4ccec5e 100644 --- a/base/bind_internal.h.pump +++ b/base/bind_internal.h.pump @@ -82,6 +82,17 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + +$if ARITY > 0 [[ + + // Target type for each bound parameter. + +$for ARG [[ + typedef X$(ARG) B$(ARG); + +]] $$ for ARG +]] $$ if ARITY > 0 + }; // Method: Arity $(ARITY). @@ -90,6 +101,15 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + +$for ARG [[ + typedef X$(ARG) B$(ARG + 1); + +]] $$ for ARG + }; // Const Method: Arity $(ARITY). @@ -98,6 +118,15 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + + // Target type for each bound parameter. + typedef T B1; + +$for ARG [[ + typedef X$(ARG) B$(ARG + 1); + +]] $$ for ARG + }; ]] $$for ARITY @@ -151,17 +180,9 @@ template <typename StorageType, typename R[[]] $if ARITY > 0 [[,]][[]] $for ARG , [[typename X$(ARG)]]> struct Invoker$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> { -$if ARITY > 0 [[ - - COMPILE_ASSERT( - !($for ARG || [[ is_non_const_reference<X$(ARG)>::value ]]), - do_not_bind_functions_with_nonconst_ref); - -]] - static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND != 0 [[, ]][[]] -$for UNBOUND_ARG , [[const X$(UNBOUND_ARG)& x$(UNBOUND_ARG)]]) { +$for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]] $$ Add comma if there are both boudn and unbound args. @@ -176,17 +197,9 @@ $if BOUND > 0 [[ template <typename StorageType, typename R, typename T[[]] $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> struct Invoker$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { -$if M_ARITY > 0 [[ - - COMPILE_ASSERT( - !($for M_ARG || [[ is_non_const_reference<X$(M_ARG)>::value ]]), - do_not_bind_functions_with_nonconst_ref); - -]] - static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND > 0 [[, ]][[]] -$for M_UNBOUND_ARG , [[const X$(M_UNBOUND_ARG)& x$(M_UNBOUND_ARG)]]) { +$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)([[]] $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] @@ -228,6 +241,7 @@ class InvokerStorage$(BOUND) : public InvokerStorageBase { typedef FunctionTraits<Sig> TargetTraits; typedef Invoker$(BOUND)<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + $for BOUND_ARG [[ $if BOUND_ARG == 1 [[ @@ -247,6 +261,19 @@ $if BOUND_ARG == 1 [[ ]] $$ $for BOUND_ARG +$if BOUND > 0 [[ + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !($for BOUND_ARG || [[ is_non_const_reference<typename TargetTraits::B$(BOUND_ARG)>::value ]]), + do_not_bind_functions_with_nonconst_ref); + +]] + InvokerStorage$(BOUND)(Sig f $if BOUND > 0 [[, ]] @@ -256,7 +283,7 @@ $if BOUND == 0 [[ { ]] $else [[ -, $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename BindType<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] { +, $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename ParamTraits<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] { MaybeRefcount<IsMethod, P1>::AddRef(p1_); ]] @@ -273,7 +300,7 @@ $if BOUND > 0 [[ Sig f_; $for BOUND_ARG [[ - typename BindType<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_; + typename ParamTraits<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_; ]] }; diff --git a/base/bind_internal_win.h b/base/bind_internal_win.h index dab8d51..976a4d7 100644 --- a/base/bind_internal_win.h +++ b/base/bind_internal_win.h @@ -3,6 +3,7 @@ // DO NOT EDIT BY HAND!!! + // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -39,6 +40,8 @@ template <typename R, typename X1> struct FunctionTraits<R(__stdcall *)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; }; // __fastcall Function: Arity 1. @@ -46,6 +49,8 @@ template <typename R, typename X1> struct FunctionTraits<R(__fastcall *)(X1)> { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; }; // __stdcall Function: Arity 2. @@ -53,6 +58,9 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(__stdcall *)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; }; // __fastcall Function: Arity 2. @@ -60,6 +68,9 @@ template <typename R, typename X1, typename X2> struct FunctionTraits<R(__fastcall *)(X1, X2)> { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; }; // __stdcall Function: Arity 3. @@ -67,6 +78,10 @@ template <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(__stdcall *)(X1, X2, X3)> { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; }; // __fastcall Function: Arity 3. @@ -74,6 +89,10 @@ template <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(__fastcall *)(X1, X2, X3)> { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; }; // __stdcall Function: Arity 4. @@ -81,6 +100,11 @@ template <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4)> { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; }; // __fastcall Function: Arity 4. @@ -88,6 +112,11 @@ template <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4)> { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; }; // __stdcall Function: Arity 5. @@ -96,6 +125,12 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; }; // __fastcall Function: Arity 5. @@ -104,6 +139,12 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; }; // __stdcall Function: Arity 6. @@ -112,6 +153,13 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5, X6)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + typedef X6 B6; }; // __fastcall Function: Arity 6. @@ -120,6 +168,13 @@ template <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5, X6)> { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + // Target type for each bound parameter. + typedef X1 B1; + typedef X2 B2; + typedef X3 B3; + typedef X4 B4; + typedef X5 B5; + typedef X6 B6; }; } // namespace internal diff --git a/base/bind_internal_win.h.pump b/base/bind_internal_win.h.pump index 4d213a3..06ceaca 100644 --- a/base/bind_internal_win.h.pump +++ b/base/bind_internal_win.h.pump @@ -34,6 +34,16 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(__stdcall *)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + +$if ARITY > 0 [[ + + // Target type for each bound parameter. + +$for ARG [[ + typedef X$(ARG) B$(ARG); + +]] $$ for ARG +]] $$ if ARITY > 0 }; // __fastcall Function: Arity $(ARITY). @@ -42,6 +52,16 @@ $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> struct FunctionTraits<R(__fastcall *)($for ARG , [[X$(ARG)]])> { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + +$if ARITY > 0 [[ + + // Target type for each bound parameter. + +$for ARG [[ + typedef X$(ARG) B$(ARG); + +]] $$ for ARG +]] $$ if ARITY > 0 }; ]] $$for ARITY diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index 061808b..c131a86 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc @@ -48,6 +48,11 @@ class HasRef : public NoRef { DISALLOW_COPY_AND_ASSIGN(HasRef); }; +class HasRefPrivateDtor : public HasRef { + private: + ~HasRefPrivateDtor() {} +}; + static const int kParentValue = 1; static const int kChildValue = 2; @@ -174,6 +179,10 @@ int UnwrapNoRefParentConstRef(const NoRefParent& p) { return p.value; } +void RefArgSet(int &n) { + n = 2; +} + // Only useful in no-compile tests. int UnwrapNoRefParentRef(Parent& p) { return p.value; @@ -351,6 +360,37 @@ TEST_F(BindTest, ArgumentBinding) { EXPECT_EQ(8, bind_const_reference_promotes_cb.Run()); } +// Unbound argument type support tests. +// - Unbound value. +// - Unbound pointer. +// - Unbound reference. +// - Unbound const reference. +// - Unbound unsized array. +// - Unbound sized array. +// - Unbound array-of-arrays. +TEST_F(BindTest, UnboundArgumentTypeSupport) { + Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic1<int>); + Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic1<int*>); + Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic1<int&>); + Callback<void(const int&)> unbound_const_ref_cb = + Bind(&VoidPolymorphic1<const int&>); + Callback<void(int[])> unbound_unsized_array_cb = + Bind(&VoidPolymorphic1<int[]>); + Callback<void(int[2])> unbound_sized_array_cb = + Bind(&VoidPolymorphic1<int[2]>); + Callback<void(int[][2])> unbound_array_of_arrays_cb = + Bind(&VoidPolymorphic1<int[][2]>); +} + +// Function with unbound reference parameter. +// - Original paraemter is modified by callback. +TEST_F(BindTest, UnboundReferenceSupport) { + int n = 0; + Callback<void(int&)> unbound_ref_cb = Bind(&RefArgSet); + unbound_ref_cb.Run(n); + EXPECT_EQ(2, n); +} + // Functions that take reference parameters. // - Forced reference parameter type still stores a copy. // - Forced const reference parameter type still stores a copy. @@ -390,6 +430,11 @@ TEST_F(BindTest, ArrayArgumentBinding) { // Verify SupportsAddRefAndRelease correctly introspects the class type for // AddRef() and Release(). +// - Class with AddRef() and Release() +// - Class without AddRef() and Release() +// - Derived Class with AddRef() and Release() +// - Derived Class without AddRef() and Release() +// - Derived Class with AddRef() and Release() and a private destructor. TEST_F(BindTest, SupportsAddRefAndRelease) { EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRef>::value); EXPECT_FALSE(internal::SupportsAddRefAndRelease<NoRef>::value); @@ -399,6 +444,10 @@ TEST_F(BindTest, SupportsAddRefAndRelease) { // inheritance. EXPECT_TRUE(internal::SupportsAddRefAndRelease<StrictMock<HasRef> >::value); EXPECT_FALSE(internal::SupportsAddRefAndRelease<StrictMock<NoRef> >::value); + + // This matters because the implementation creates a dummy class that + // inherits from the template type. + EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRefPrivateDtor>::value); } // Unretained() wrapper support. @@ -570,14 +619,13 @@ TEST_F(BindTest, NoCompile) { // // HasRef p[10]; // Callback<void(void)> method_bound_to_array_cb = - // Bind(&HasRef::VoidConstMethod0, p); + // Bind(&HasRef::VoidConstMethod0, p); // method_bound_to_array_cb.Run(); // - Refcounted types should not be bound as a raw pointer. // HasRef for_raw_ptr; // Callback<void(void)> ref_count_as_raw_ptr = // Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr); - // ASSERT_EQ(&for_raw_ptr, ref_count_as_raw_ptr.Run()); } diff --git a/base/bzip2_error_handler.cc b/base/bzip2_error_handler.cc index 564cabd..e66bcf3 100644 --- a/base/bzip2_error_handler.cc +++ b/base/bzip2_error_handler.cc @@ -1,7 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <ostream> + #include "base/logging.h" // We define BZ_NO_STDIO in third_party/bzip2 to remove its internal STDERR diff --git a/base/callback.h b/base/callback.h index bcc3dfd..dafbc0c 100644 --- a/base/callback.h +++ b/base/callback.h @@ -3,6 +3,7 @@ // DO NOT EDIT BY HAND!!! + // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -44,8 +45,8 @@ // // /* Binding a normal function. */ // int Return5() { return 5; } -// base::Callback<int(int)> func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(5); // Prints 5. +// base::Callback<int(void)> func_cb = base::Bind(&Return5); +// LOG(INFO) << func_cb.Run(); // Prints 5. // // void PrintHi() { LOG(INFO) << "hi."; } // base::Closure void_func_cb = base::Bind(&PrintHi); @@ -188,7 +189,7 @@ // // These are not features that are required in Chromium. Some of them, such as // allowing for reference parameters, and subtyping of functions, may actually -// because a source of errors. Removing support for these features actually +// become a source of errors. Removing support for these features actually // allows for a simpler implementation, and a terser Currying API. // // @@ -225,7 +226,8 @@ class Callback; template <typename R> class Callback<R(void)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*); Callback() : CallbackBase(NULL, NULL) { } @@ -254,7 +256,9 @@ class Callback<R(void)> : public internal::CallbackBase { template <typename R, typename A1> class Callback<R(A1)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -272,7 +276,7 @@ class Callback<R(A1)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -283,8 +287,10 @@ class Callback<R(A1)> : public internal::CallbackBase { template <typename R, typename A1, typename A2> class Callback<R(A1, A2)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -302,8 +308,8 @@ class Callback<R(A1, A2)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -315,9 +321,11 @@ class Callback<R(A1, A2)> : public internal::CallbackBase { template <typename R, typename A1, typename A2, typename A3> class Callback<R(A1, A2, A3)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -335,9 +343,9 @@ class Callback<R(A1, A2, A3)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -350,10 +358,12 @@ class Callback<R(A1, A2, A3)> : public internal::CallbackBase { template <typename R, typename A1, typename A2, typename A3, typename A4> class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&, - const A4&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType, + typename internal::ParamTraits<A4>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -371,10 +381,10 @@ class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3, + typename internal::ParamTraits<A4>::ForwardType a4) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -389,11 +399,13 @@ template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5> class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&, - const A4&, - const A5&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType, + typename internal::ParamTraits<A4>::ForwardType, + typename internal::ParamTraits<A5>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -411,11 +423,11 @@ class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4, - const A5& a5) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3, + typename internal::ParamTraits<A4>::ForwardType a4, + typename internal::ParamTraits<A5>::ForwardType a5) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); @@ -431,12 +443,14 @@ template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, - const A2&, - const A3&, - const A4&, - const A5&, - const A6&); + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*, + typename internal::ParamTraits<A1>::ForwardType, + typename internal::ParamTraits<A2>::ForwardType, + typename internal::ParamTraits<A3>::ForwardType, + typename internal::ParamTraits<A4>::ForwardType, + typename internal::ParamTraits<A5>::ForwardType, + typename internal::ParamTraits<A6>::ForwardType); Callback() : CallbackBase(NULL, NULL) { } @@ -454,12 +468,12 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { &invoker_holder.invoker_storage_) { } - R Run(const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4, - const A5& a5, - const A6& a6) const { + R Run(typename internal::ParamTraits<A1>::ForwardType a1, + typename internal::ParamTraits<A2>::ForwardType a2, + typename internal::ParamTraits<A3>::ForwardType a3, + typename internal::ParamTraits<A4>::ForwardType a4, + typename internal::ParamTraits<A5>::ForwardType a5, + typename internal::ParamTraits<A6>::ForwardType a6) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); diff --git a/base/callback.h.pump b/base/callback.h.pump index 34b0eb0..542a84f 100644 --- a/base/callback.h.pump +++ b/base/callback.h.pump @@ -240,10 +240,10 @@ class Callback<R($for ARG , [[A$(ARG)]])> : public internal::CallbackBase { ]] public: - typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*[[]] + typedef R(*PolymorphicInvoke)( + internal::InvokerStorageBase*[[]] $if ARITY != 0 [[, ]] -$for ARG , - [[const A$(ARG)&]]); +$for ARG , [[typename internal::ParamTraits<A$(ARG)>::ForwardType]]); Callback() : CallbackBase(NULL, NULL) { } @@ -262,7 +262,7 @@ $for ARG , } R Run($for ARG , - [[const A$(ARG)& a$(ARG)]]) const { + [[typename internal::ParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); diff --git a/base/callback_internal.h b/base/callback_internal.h index 4f1d3c3..b83b049 100644 --- a/base/callback_internal.h +++ b/base/callback_internal.h @@ -9,7 +9,10 @@ #define BASE_CALLBACK_INTERNAL_H_ #pragma once -#include "base/ref_counted.h" +#include <stddef.h> + +#include "base/base_api.h" +#include "base/memory/ref_counted.h" namespace base { namespace internal { @@ -51,7 +54,7 @@ InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) { // Holds the Callback methods that don't require specialization to reduce // template bloat. -class CallbackBase { +class BASE_API CallbackBase { public: // Returns true if Callback is null (doesn't refer to anything). bool is_null() const; @@ -80,6 +83,52 @@ class CallbackBase { InvokeFuncStorage polymorphic_invoke_; }; +// This is a typetraits object that's used to take an argument type, and +// extract a suitable type for storing and forwarding arguments. +// +// In particular, it strips off references, and converts arrays to +// pointers for storage; and it avoids accidentally trying to create a +// "reference of a reference" if the argument is a reference type. +// +// This array type becomes an issue for storage because we are passing bound +// parameters by const reference. In this case, we end up passing an actual +// array type in the initializer list which C++ does not allow. This will +// break passing of C-string literals. +template <typename T> +struct ParamTraits { + typedef const T& ForwardType; + typedef T StorageType; +}; + +// The Storage should almost be impossible to trigger unless someone manually +// specifies type of the bind parameters. However, in case they do, +// this will guard against us accidentally storing a reference parameter. +// +// The ForwardType should only be used for unbound arguments. +template <typename T> +struct ParamTraits<T&> { + typedef T& ForwardType; + typedef T StorageType; +}; + +// Note that for array types, we implicitly add a const in the conversion. This +// means that it is not possible to bind array arguments to functions that take +// a non-const pointer. Trying to specialize the template based on a "const +// T[n]" does not seem to match correctly, so we are stuck with this +// restriction. +template <typename T, size_t n> +struct ParamTraits<T[n]> { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + +// See comment for ParamTraits<T[n]>. +template <typename T> +struct ParamTraits<T[]> { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + } // namespace internal } // namespace base diff --git a/base/callback_old.h b/base/callback_old.h index ab3927d..7719e66 100644 --- a/base/callback_old.h +++ b/base/callback_old.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,8 +6,8 @@ #define BASE_CALLBACK_OLD_H_ #pragma once +#include "base/memory/raw_scoped_refptr_mismatch_checker.h" #include "base/tuple.h" -#include "base/raw_scoped_refptr_mismatch_checker.h" // Callback -------------------------------------------------------------------- // diff --git a/base/callback_unittest.cc b/base/callback_unittest.cc index f327412..da2f150 100644 --- a/base/callback_unittest.cc +++ b/base/callback_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/callback.h" #include "base/callback_internal.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/command_line.cc b/base/command_line.cc index fcb2294..b027d2a 100644 --- a/base/command_line.cc +++ b/base/command_line.cc @@ -5,24 +5,19 @@ #include "base/command_line.h" #include <algorithm> +#include <ostream> +#include "base/basictypes.h" #include "base/file_path.h" -#include "base/file_util.h" #include "base/logging.h" -#include "base/singleton.h" #include "base/string_split.h" #include "base/string_util.h" -#include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" #include "build/build_config.h" #if defined(OS_WIN) #include <windows.h> #include <shellapi.h> -#elif defined(OS_POSIX) -#include <limits.h> -#include <stdlib.h> -#include <unistd.h> #endif CommandLine* CommandLine::current_process_commandline_ = NULL; diff --git a/base/command_line.h b/base/command_line.h index 7ff5ab0..970e4a7 100644 --- a/base/command_line.h +++ b/base/command_line.h @@ -15,16 +15,17 @@ #define BASE_COMMAND_LINE_H_ #pragma once +#include <stddef.h> #include <map> #include <string> #include <vector> -#include "base/basictypes.h" +#include "base/base_api.h" #include "build/build_config.h" class FilePath; -class CommandLine { +class BASE_API CommandLine { public: #if defined(OS_WIN) // The native command line string type. diff --git a/base/compiler_specific.h b/base/compiler_specific.h index 3060306..43ff21c 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -74,8 +74,10 @@ // int x ALLOW_UNUSED = ...; #if defined(COMPILER_GCC) #define ALLOW_UNUSED __attribute__((unused)) +#define NOINLINE __attribute__((noinline)) #else #define ALLOW_UNUSED +#define NOINLINE #endif // Annotate a virtual method indicating it must be overriding a virtual diff --git a/base/cpu.cc b/base/cpu.cc index 3232f15..f45e966 100644 --- a/base/cpu.cc +++ b/base/cpu.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -120,6 +120,4 @@ void CPU::Initialize() { #endif } - - } // namespace base @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,14 +6,14 @@ #define BASE_CPU_H_ #pragma once -#include "build/build_config.h" - #include <string> +#include "base/base_api.h" + namespace base { // Query information about the processor. -class CPU { +class BASE_API CPU { public: // Constructor CPU(); diff --git a/base/crypto/capi_util.cc b/base/crypto/capi_util.cc deleted file mode 100644 index ef57a3c..0000000 --- a/base/crypto/capi_util.cc +++ /dev/null @@ -1,50 +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/crypto/capi_util.h" - -#include "base/basictypes.h" -#include "base/singleton.h" -#include "base/synchronization/lock.h" - -namespace { - -class CAPIUtilSingleton { - public: - static CAPIUtilSingleton* GetInstance() { - return Singleton<CAPIUtilSingleton>::get(); - } - - // Returns a lock to guard calls to CryptAcquireContext with - // CRYPT_DELETEKEYSET or CRYPT_NEWKEYSET. - base::Lock& acquire_context_lock() { - return acquire_context_lock_; - } - - private: - friend class Singleton<CAPIUtilSingleton>; - friend struct DefaultSingletonTraits<CAPIUtilSingleton>; - - CAPIUtilSingleton() {} - - base::Lock acquire_context_lock_; - - DISALLOW_COPY_AND_ASSIGN(CAPIUtilSingleton); -}; - -} // namespace - -namespace base { - -BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, - LPCWSTR container, - LPCWSTR provider, - DWORD prov_type, - DWORD flags) -{ - base::AutoLock lock(CAPIUtilSingleton::GetInstance()->acquire_context_lock()); - return CryptAcquireContext(prov, container, provider, prov_type, flags); -} - -} // namespace base diff --git a/base/crypto/capi_util.h b/base/crypto/capi_util.h deleted file mode 100644 index df7f749..0000000 --- a/base/crypto/capi_util.h +++ /dev/null @@ -1,32 +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_CRYPTO_CAPI_UTIL_H_ -#define BASE_CRYPTO_CAPI_UTIL_H_ -#pragma once - -#include <windows.h> -#include <wincrypt.h> - -namespace base { - -// CryptAcquireContext when passed CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET in -// flags is not thread-safe. For such calls, we create a global lock to -// synchronize it. -// -// From "Threading Issues with Cryptographic Service Providers", -// <http://msdn.microsoft.com/en-us/library/aa388149(v=VS.85).aspx>: -// -// "The CryptAcquireContext function is generally thread safe unless -// CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET is specified in the dwFlags -// parameter." -BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, - LPCWSTR container, - LPCWSTR provider, - DWORD prov_type, - DWORD flags); - -} // namespace base - -#endif // BASE_CRYPTO_CAPI_UTIL_H_ diff --git a/base/crypto/crypto_module_blocking_password_delegate.h b/base/crypto/crypto_module_blocking_password_delegate.h deleted file mode 100644 index ae962a8..0000000 --- a/base/crypto/crypto_module_blocking_password_delegate.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_ -#define BASE_CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_ -#pragma once - -#include <string> - -namespace base { - -// PK11_SetPasswordFunc is a global setting. An implementation of -// CryptoModuleBlockingPasswordDelegate should be passed as the user data -// argument (|wincx|) to relevant NSS functions, which the global password -// handler will call to do the actual work. -class CryptoModuleBlockingPasswordDelegate { - public: - virtual ~CryptoModuleBlockingPasswordDelegate() {} - - // Requests a password to unlock |slot_name|. The interface is - // synchronous because NSS cannot issue an asynchronous - // request. |retry| is true if this is a request for the retry - // and we previously returned the wrong password. - // The implementation should set |*cancelled| to true if the user cancelled - // instead of entering a password, otherwise it should return the password the - // user entered. - virtual std::string RequestPassword(const std::string& slot_name, bool retry, - bool* cancelled) = 0; -}; - -} - -#endif // BASE_CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_ diff --git a/base/crypto/cssm_init.cc b/base/crypto/cssm_init.cc deleted file mode 100644 index 570dcc3..0000000 --- a/base/crypto/cssm_init.cc +++ /dev/null @@ -1,231 +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/crypto/cssm_init.h" - -#include <Security/SecBase.h> - -#include "base/logging.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/singleton.h" -#include "base/synchronization/lock.h" -#include "base/sys_string_conversions.h" - -// When writing crypto code for Mac OS X, you may find the following -// documentation useful: -// - Common Security: CDSA and CSSM, Version 2 (with corrigenda) -// http://www.opengroup.org/security/cdsa.htm -// - Apple Cryptographic Service Provider Functional Specification -// - CryptoSample: http://developer.apple.com/SampleCode/CryptoSample/ - -namespace { - -void* CSSMMalloc(CSSM_SIZE size, void* alloc_ref) { - return malloc(size); -} - -void CSSMFree(void* mem_ptr, void* alloc_ref) { - free(mem_ptr); -} - -void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) { - return realloc(ptr, size); -} - -void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) { - return calloc(num, size); -} - -class CSSMInitSingleton { - public: - static CSSMInitSingleton* GetInstance() { - return Singleton<CSSMInitSingleton, - LeakySingletonTraits<CSSMInitSingleton> >::get(); - } - - CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; } - CSSM_CL_HANDLE cl_handle() const { return cl_handle_; } - CSSM_TP_HANDLE tp_handle() const { return tp_handle_; } - - private: - CSSMInitSingleton() - : inited_(false), csp_loaded_(false), cl_loaded_(false), - tp_loaded_(false), csp_handle_(NULL), cl_handle_(NULL), - tp_handle_(NULL) { - static CSSM_VERSION version = {2, 0}; - // TODO(wtc): what should our caller GUID be? - static const CSSM_GUID test_guid = { - 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } - }; - CSSM_RETURN crtn; - CSSM_PVC_MODE pvc_policy = CSSM_PVC_NONE; - crtn = CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &test_guid, - CSSM_KEY_HIERARCHY_NONE, &pvc_policy, NULL); - if (crtn) { - NOTREACHED(); - return; - } - inited_ = true; - - crtn = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); - if (crtn) { - NOTREACHED(); - return; - } - csp_loaded_ = true; - crtn = CSSM_ModuleLoad( - &gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); - if (crtn) { - NOTREACHED(); - return; - } - cl_loaded_ = true; - crtn = CSSM_ModuleLoad( - &gGuidAppleX509TP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); - if (crtn) { - NOTREACHED(); - return; - } - tp_loaded_ = true; - - const CSSM_API_MEMORY_FUNCS cssmMemoryFunctions = { - CSSMMalloc, - CSSMFree, - CSSMRealloc, - CSSMCalloc, - NULL - }; - - crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &cssmMemoryFunctions, 0, - CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, - NULL, 0, NULL, &csp_handle_); - DCHECK(crtn == CSSM_OK); - crtn = CSSM_ModuleAttach(&gGuidAppleX509CL, &version, &cssmMemoryFunctions, - 0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE, - NULL, 0, NULL, &cl_handle_); - DCHECK(crtn == CSSM_OK); - crtn = CSSM_ModuleAttach(&gGuidAppleX509TP, &version, &cssmMemoryFunctions, - 0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE, - NULL, 0, NULL, &tp_handle_); - DCHECK(crtn == CSSM_OK); - } - - ~CSSMInitSingleton() { - CSSM_RETURN crtn; - if (csp_handle_) { - CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_); - DCHECK(crtn == CSSM_OK); - } - if (cl_handle_) { - CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_); - DCHECK(crtn == CSSM_OK); - } - if (tp_handle_) { - CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_); - DCHECK(crtn == CSSM_OK); - } - if (csp_loaded_) { - crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL); - DCHECK(crtn == CSSM_OK); - } - if (cl_loaded_) { - crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); - DCHECK(crtn == CSSM_OK); - } - if (tp_loaded_) { - crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); - DCHECK(crtn == CSSM_OK); - } - if (inited_) { - crtn = CSSM_Terminate(); - DCHECK(crtn == CSSM_OK); - } - } - - bool inited_; // True if CSSM_Init has been called successfully. - bool csp_loaded_; // True if gGuidAppleCSP has been loaded - bool cl_loaded_; // True if gGuidAppleX509CL has been loaded. - bool tp_loaded_; // True if gGuidAppleX509TP has been loaded. - CSSM_CSP_HANDLE csp_handle_; - CSSM_CL_HANDLE cl_handle_; - CSSM_TP_HANDLE tp_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, - LeakySingletonTraits<SecurityServicesSingleton> >::get(); - } - - base::Lock& lock() { return lock_; } - - private: - friend struct DefaultSingletonTraits<SecurityServicesSingleton>; - - SecurityServicesSingleton() {} - ~SecurityServicesSingleton() {} - - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(SecurityServicesSingleton); -}; - -} // namespace - -namespace base { - -void EnsureCSSMInit() { - CSSMInitSingleton::GetInstance(); -} - -CSSM_CSP_HANDLE GetSharedCSPHandle() { - return CSSMInitSingleton::GetInstance()->csp_handle(); -} - -CSSM_CL_HANDLE GetSharedCLHandle() { - return CSSMInitSingleton::GetInstance()->cl_handle(); -} - -CSSM_TP_HANDLE GetSharedTPHandle() { - return CSSMInitSingleton::GetInstance()->tp_handle(); -} - -void* CSSMMalloc(CSSM_SIZE size) { - return ::CSSMMalloc(size, NULL); -} - -void CSSMFree(void* ptr) { - ::CSSMFree(ptr, NULL); -} - -void LogCSSMError(const char* fn_name, CSSM_RETURN err) { - if (!err) - return; - base::mac::ScopedCFTypeRef<CFStringRef> cfstr( - SecCopyErrorMessageString(err, NULL)); - LOG(ERROR) << fn_name << " returned " << err - << " (" << SysCFStringRefToUTF8(cfstr) << ")"; -} - -base::Lock& GetMacSecurityServicesLock() { - return SecurityServicesSingleton::GetInstance()->lock(); -} - -ScopedCSSMData::ScopedCSSMData() { - memset(&data_, 0, sizeof(data_)); -} - -ScopedCSSMData::~ScopedCSSMData() { - if (data_.Data) { - CSSMFree(data_.Data); - data_.Data = NULL; - } -} - -} // namespace base diff --git a/base/crypto/cssm_init.h b/base/crypto/cssm_init.h deleted file mode 100644 index b51a3b5..0000000 --- a/base/crypto/cssm_init.h +++ /dev/null @@ -1,69 +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_CRYPTO_CSSM_INIT_H_ -#define BASE_CRYPTO_CSSM_INIT_H_ -#pragma once - -#include <Security/cssm.h> - -#include "base/basictypes.h" - -namespace base { - -class Lock; - -// Initialize CSSM if it isn't already initialized. This must be called before -// any other CSSM functions. This function is thread-safe, and CSSM will only -// ever be initialized once. CSSM will be properly shut down on program exit. -void EnsureCSSMInit(); - -// Returns the shared CSP handle used by CSSM functions. -CSSM_CSP_HANDLE GetSharedCSPHandle(); - -// Returns the shared CL handle used by CSSM functions. -CSSM_CL_HANDLE GetSharedCLHandle(); - -// Returns the shared TP handle used by CSSM functions. -CSSM_TP_HANDLE GetSharedTPHandle(); - -// Set of pointers to memory function wrappers that are required for CSSM -extern const CSSM_API_MEMORY_FUNCS kCssmMemoryFunctions; - -// Utility function to log an error message including the error name. -void LogCSSMError(const char *function_name, CSSM_RETURN err); - -// Utility functions to allocate and release CSSM memory. -void* CSSMMalloc(CSSM_SIZE size); -void CSSMFree(void* ptr); - -// The OS X certificate and key management wrappers over CSSM are not -// thread-safe. In particular, code that accesses the CSSM database is -// problematic. -// -// http://developer.apple.com/mac/library/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html -Lock& GetMacSecurityServicesLock(); - -// Wrapper class for CSSM_DATA type. This should only be used when using the -// CL/TP/CSP handles from above, since that's the only time we're guaranteed (or -// supposed to be guaranteed) that our memory management functions will be used. -// Apple's Sec* APIs manage their own memory so it shouldn't be used for those. -// The constructor initializes data_ to zero and the destructor releases the -// data properly. -class ScopedCSSMData { - public: - ScopedCSSMData(); - ~ScopedCSSMData(); - operator CSSM_DATA*() { return &data_; } - CSSM_DATA* operator ->() { return &data_; } - - private: - CSSM_DATA data_; - - DISALLOW_COPY_AND_ASSIGN(ScopedCSSMData); -}; - -} // namespace base - -#endif // BASE_CRYPTO_CSSM_INIT_H_ diff --git a/base/crypto/encryptor.h b/base/crypto/encryptor.h deleted file mode 100644 index 7718240..0000000 --- a/base/crypto/encryptor.h +++ /dev/null @@ -1,69 +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_CRYPTO_ENCRYPTOR_H_ -#define BASE_CRYPTO_ENCRYPTOR_H_ -#pragma once - -#include <string> - -#include "build/build_config.h" - -#if defined(USE_NSS) -#include "base/crypto/scoped_nss_types.h" -#elif defined(OS_WIN) -#include "base/crypto/scoped_capi_types.h" -#endif - -namespace base { - -class SymmetricKey; - -class Encryptor { - public: - enum Mode { - CBC - }; - Encryptor(); - virtual ~Encryptor(); - - // Initializes the encryptor using |key| and |iv|. Returns false if either the - // key or the initialization vector cannot be used. - bool Init(SymmetricKey* key, Mode mode, const std::string& iv); - - // Encrypts |plaintext| into |ciphertext|. - bool Encrypt(const std::string& plaintext, std::string* ciphertext); - - // Decrypts |ciphertext| into |plaintext|. - bool Decrypt(const std::string& ciphertext, std::string* plaintext); - - // TODO(albertb): Support streaming encryption. - - private: - SymmetricKey* key_; - Mode mode_; - -#if defined(USE_OPENSSL) - bool Crypt(bool encrypt, // Pass true to encrypt, false to decrypt. - const std::string& input, - std::string* output); - std::string iv_; -#elif defined(USE_NSS) - ScopedPK11Slot slot_; - ScopedSECItem param_; -#elif defined(OS_MACOSX) - bool Crypt(int /*CCOperation*/ op, - const std::string& input, - std::string* output); - - std::string iv_; -#elif defined(OS_WIN) - ScopedHCRYPTKEY capi_key_; - DWORD block_size_; -#endif -}; - -} // namespace base - -#endif // BASE_CRYPTO_ENCRYPTOR_H_ diff --git a/base/crypto/encryptor_mac.cc b/base/crypto/encryptor_mac.cc deleted file mode 100644 index e26c6bd..0000000 --- a/base/crypto/encryptor_mac.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/crypto/encryptor.h" - -#include <CommonCrypto/CommonCryptor.h> - -#include "base/crypto/symmetric_key.h" -#include "base/logging.h" -#include "base/string_util.h" - -namespace base { - -Encryptor::Encryptor() - : key_(NULL), - mode_(CBC) { -} - -Encryptor::~Encryptor() { -} - -bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { - DCHECK(key); - DCHECK_EQ(CBC, mode) << "Unsupported mode of operation"; - CSSM_DATA raw_key = key->cssm_data(); - if (raw_key.Length != kCCKeySizeAES128 && - raw_key.Length != kCCKeySizeAES192 && - raw_key.Length != kCCKeySizeAES256) - return false; - if (iv.size() != kCCBlockSizeAES128) - return false; - - key_ = key; - mode_ = mode; - iv_ = iv; - return true; -} - -bool Encryptor::Crypt(int /*CCOperation*/ op, - const std::string& input, - std::string* output) { - DCHECK(key_); - CSSM_DATA raw_key = key_->cssm_data(); - // CommonCryptor.h: "A general rule for the size of the output buffer which - // must be provided by the caller is that for block ciphers, the output - // length is never larger than the input length plus the block size." - - size_t output_size = input.size() + iv_.size(); - CCCryptorStatus err = CCCrypt(op, - kCCAlgorithmAES128, - kCCOptionPKCS7Padding, - raw_key.Data, raw_key.Length, - iv_.data(), - input.data(), input.size(), - WriteInto(output, output_size+1), - output_size, - &output_size); - if (err) { - output->resize(0); - LOG(ERROR) << "CCCrypt returned " << err; - return false; - } - output->resize(output_size); - return true; -} - -bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { - return Crypt(kCCEncrypt, plaintext, ciphertext); -} - -bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { - return Crypt(kCCDecrypt, ciphertext, plaintext); -} - -} // namespace base diff --git a/base/crypto/encryptor_nss.cc b/base/crypto/encryptor_nss.cc deleted file mode 100644 index 3b9f7f3..0000000 --- a/base/crypto/encryptor_nss.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/crypto/encryptor.h" - -#include <cryptohi.h> -#include <vector> - -#include "base/crypto/symmetric_key.h" -#include "base/logging.h" -#include "base/nss_util.h" - -namespace base { - -Encryptor::Encryptor() - : key_(NULL), - mode_(CBC) { - EnsureNSSInit(); -} - -Encryptor::~Encryptor() { -} - -bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { - DCHECK(key); - DCHECK_EQ(CBC, mode); - - key_ = key; - mode_ = mode; - - if (iv.size() != AES_BLOCK_SIZE) - return false; - - slot_.reset(PK11_GetBestSlot(CKM_AES_CBC_PAD, NULL)); - if (!slot_.get()) - return false; - - SECItem iv_item; - iv_item.type = siBuffer; - iv_item.data = reinterpret_cast<unsigned char*>( - const_cast<char *>(iv.data())); - iv_item.len = iv.size(); - - param_.reset(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); - if (!param_.get()) - return false; - - return true; -} - -bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { - ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_AES_CBC_PAD, - CKA_ENCRYPT, - key_->key(), - param_.get())); - if (!context.get()) - return false; - - size_t ciphertext_len = plaintext.size() + AES_BLOCK_SIZE; - std::vector<unsigned char> buffer(ciphertext_len); - - int op_len; - SECStatus rv = PK11_CipherOp(context.get(), - &buffer[0], - &op_len, - ciphertext_len, - reinterpret_cast<unsigned char*>( - const_cast<char*>(plaintext.data())), - plaintext.size()); - if (SECSuccess != rv) - return false; - - unsigned int digest_len; - rv = PK11_DigestFinal(context.get(), - &buffer[op_len], - &digest_len, - ciphertext_len - op_len); - if (SECSuccess != rv) - return false; - - ciphertext->assign(reinterpret_cast<char *>(&buffer[0]), - op_len + digest_len); - return true; -} - -bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { - if (ciphertext.empty()) - return false; - - ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_AES_CBC_PAD, - CKA_DECRYPT, - key_->key(), - param_.get())); - if (!context.get()) - return false; - - size_t plaintext_len = ciphertext.size(); - std::vector<unsigned char> buffer(plaintext_len); - - int op_len; - SECStatus rv = PK11_CipherOp(context.get(), - &buffer[0], - &op_len, - plaintext_len, - reinterpret_cast<unsigned char*>( - const_cast<char*>(ciphertext.data())), - ciphertext.size()); - if (SECSuccess != rv) - return false; - - unsigned int digest_len; - rv = PK11_DigestFinal(context.get(), - &buffer[op_len], - &digest_len, - plaintext_len - op_len); - if (SECSuccess != rv) - return false; - - plaintext->assign(reinterpret_cast<char *>(&buffer[0]), - op_len + digest_len); - return true; -} - -} // namespace base diff --git a/base/crypto/encryptor_openssl.cc b/base/crypto/encryptor_openssl.cc deleted file mode 100644 index 0e101a0..0000000 --- a/base/crypto/encryptor_openssl.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/crypto/encryptor.h" - -#include <openssl/aes.h> -#include <openssl/evp.h> - -#include "base/crypto/symmetric_key.h" -#include "base/logging.h" -#include "base/openssl_util.h" -#include "base/string_util.h" - -namespace base { - -namespace { - -const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) { - switch (key->key().length()) { - case 16: return EVP_aes_128_cbc(); - case 24: return EVP_aes_192_cbc(); - case 32: return EVP_aes_256_cbc(); - default: return NULL; - } -} - -// On destruction this class will cleanup the ctx, and also clear the OpenSSL -// ERR stack as a convenience. -class ScopedCipherCTX { - public: - explicit ScopedCipherCTX() { - EVP_CIPHER_CTX_init(&ctx_); - } - ~ScopedCipherCTX() { - EVP_CIPHER_CTX_cleanup(&ctx_); - ClearOpenSSLERRStack(FROM_HERE); - } - EVP_CIPHER_CTX* get() { return &ctx_; } - - private: - EVP_CIPHER_CTX ctx_; -}; - -} // namespace - -Encryptor::Encryptor() - : key_(NULL), - mode_(CBC) { -} - -Encryptor::~Encryptor() { -} - -bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { - DCHECK(key); - DCHECK_EQ(CBC, mode); - - EnsureOpenSSLInit(); - if (iv.size() != AES_BLOCK_SIZE) - return false; - - if (GetCipherForKey(key) == NULL) - return false; - - key_ = key; - mode_ = mode; - iv_ = iv; - return true; -} - -bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { - return Crypt(true, plaintext, ciphertext); -} - -bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { - return Crypt(false, ciphertext, plaintext); -} - -bool Encryptor::Crypt(bool do_encrypt, - const std::string& input, - std::string* output) { - DCHECK(key_); // Must call Init() before En/De-crypt. - // Work on the result in a local variable, and then only transfer it to - // |output| on success to ensure no partial data is returned. - std::string result; - output->swap(result); - - const EVP_CIPHER* cipher = GetCipherForKey(key_); - DCHECK(cipher); // Already handled in Init(); - - const std::string& key = key_->key(); - DCHECK_EQ(EVP_CIPHER_iv_length(cipher), static_cast<int>(iv_.length())); - DCHECK_EQ(EVP_CIPHER_key_length(cipher), static_cast<int>(key.length())); - - ScopedCipherCTX ctx; - if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL, - reinterpret_cast<const uint8*>(key.data()), - reinterpret_cast<const uint8*>(iv_.data()), - do_encrypt)) - return false; - - // When encrypting, add another block size of space to allow for any padding. - const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0); - uint8* out_ptr = reinterpret_cast<uint8*>(WriteInto(&result, - output_size + 1)); - int out_len; - if (!EVP_CipherUpdate(ctx.get(), out_ptr, &out_len, - reinterpret_cast<const uint8*>(input.data()), - input.length())) - return false; - - // Write out the final block plus padding (if any) to the end of the data - // just written. - int tail_len; - if (!EVP_CipherFinal_ex(ctx.get(), out_ptr + out_len, &tail_len)) - return false; - - out_len += tail_len; - DCHECK_LE(out_len, static_cast<int>(output_size)); - result.resize(out_len); - - output->swap(result); - return true; -} - -} // namespace base diff --git a/base/crypto/encryptor_unittest.cc b/base/crypto/encryptor_unittest.cc deleted file mode 100644 index e8d055b..0000000 --- a/base/crypto/encryptor_unittest.cc +++ /dev/null @@ -1,232 +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/crypto/encryptor.h" - -#include <string> - -#include "base/crypto/symmetric_key.h" -#include "base/scoped_ptr.h" -#include "base/string_number_conversions.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(EncryptorTest, EncryptDecrypt) { - scoped_ptr<base::SymmetricKey> key(base::SymmetricKey::DeriveKeyFromPassword( - base::SymmetricKey::AES, "password", "saltiest", 1000, 256)); - EXPECT_TRUE(NULL != key.get()); - - base::Encryptor encryptor; - // The IV must be exactly as long as the cipher block size. - std::string iv("the iv: 16 bytes"); - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(key.get(), base::Encryptor::CBC, iv)); - - std::string plaintext("this is the plaintext"); - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - - EXPECT_LT(0U, ciphertext.size()); - - std::string decypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted)); - - EXPECT_EQ(plaintext, decypted); -} - -// TODO(wtc): add more known-answer tests. Test vectors are available from -// http://www.ietf.org/rfc/rfc3602 -// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf -// http://gladman.plushost.co.uk/oldsite/AES/index.php -// http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip - -// NIST SP 800-38A test vector F.2.5 CBC-AES256.Encrypt. -TEST(EncryptorTest, EncryptAES256CBC) { - // From NIST SP 800-38a test cast F.2.5 CBC-AES256.Encrypt. - static const unsigned char raw_key[] = { - 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, - 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, - 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, - 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 - }; - static const unsigned char raw_iv[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - }; - static const unsigned char raw_plaintext[] = { - // Block #1 - 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - // Block #2 - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - // Block #3 - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - // Block #4 - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, - }; - static const unsigned char raw_ciphertext[] = { - // Block #1 - 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, - 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, - // Block #2 - 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, - 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, - // Block #3 - 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, - 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, - // Block #4 - 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, - 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b, - // PKCS #5 padding, encrypted. - 0x3f, 0x46, 0x17, 0x96, 0xd6, 0xb0, 0xd6, 0xb2, - 0xe0, 0xc2, 0xa7, 0x2b, 0x4d, 0x80, 0xe6, 0x44 - }; - - std::string key(reinterpret_cast<const char*>(raw_key), sizeof(raw_key)); - scoped_ptr<base::SymmetricKey> sym_key(base::SymmetricKey::Import( - base::SymmetricKey::AES, key)); - ASSERT_TRUE(NULL != sym_key.get()); - - base::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - std::string iv(reinterpret_cast<const char*>(raw_iv), sizeof(raw_iv)); - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); - - std::string plaintext(reinterpret_cast<const char*>(raw_plaintext), - sizeof(raw_plaintext)); - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - - EXPECT_EQ(sizeof(raw_ciphertext), ciphertext.size()); - EXPECT_EQ(0, memcmp(ciphertext.data(), raw_ciphertext, ciphertext.size())); - - std::string decypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted)); - - EXPECT_EQ(plaintext, decypted); -} - -// Expected output derived from the NSS implementation. -TEST(EncryptorTest, EncryptAES128CBCRegression) { - std::string key = "128=SixteenBytes"; - std::string iv = "Sweet Sixteen IV"; - std::string plaintext = "Plain text with a g-clef U+1D11E \360\235\204\236"; - std::string expected_ciphertext_hex = - "D4A67A0BA33C30F207344D81D1E944BBE65587C3D7D9939A" - "C070C62B9C15A3EA312EA4AD1BC7929F4D3C16B03AD5ADA8"; - - scoped_ptr<base::SymmetricKey> sym_key(base::SymmetricKey::Import( - base::SymmetricKey::AES, key)); - ASSERT_TRUE(NULL != sym_key.get()); - - base::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); - - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), - ciphertext.size())); - - std::string decypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted)); - EXPECT_EQ(plaintext, decypted); -} - -// Expected output derived from the NSS implementation. -TEST(EncryptorTest, EncryptAES192CBCRegression) { - std::string key = "192bitsIsTwentyFourByte!"; - std::string iv = "Sweet Sixteen IV"; - std::string plaintext = "Small text"; - std::string expected_ciphertext_hex = "78DE5D7C2714FC5C61346C5416F6C89A"; - - scoped_ptr<base::SymmetricKey> sym_key(base::SymmetricKey::Import( - base::SymmetricKey::AES, key)); - ASSERT_TRUE(NULL != sym_key.get()); - - base::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); - - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), - ciphertext.size())); - - std::string decypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted)); - EXPECT_EQ(plaintext, decypted); -} - -// Not all platforms allow import/generation of symmetric keys with an -// unsupported size. -#if !defined(OS_WIN) && !defined(USE_NSS) -TEST(EncryptorTest, UnsupportedKeySize) { - std::string key = "7 = bad"; - std::string iv = "Sweet Sixteen IV"; - scoped_ptr<base::SymmetricKey> sym_key(base::SymmetricKey::Import( - base::SymmetricKey::AES, key)); - ASSERT_TRUE(NULL != sym_key.get()); - - base::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_FALSE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); -} -#endif // unsupported platforms. - -TEST(EncryptorTest, UnsupportedIV) { - std::string key = "128=SixteenBytes"; - std::string iv = "OnlyForteen :("; - scoped_ptr<base::SymmetricKey> sym_key(base::SymmetricKey::Import( - base::SymmetricKey::AES, key)); - ASSERT_TRUE(NULL != sym_key.get()); - - base::Encryptor encryptor; - EXPECT_FALSE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); -} - -TEST(EncryptorTest, EmptyEncrypt) { - std::string key = "128=SixteenBytes"; - std::string iv = "Sweet Sixteen IV"; - std::string plaintext; - std::string expected_ciphertext_hex = "8518B8878D34E7185E300D0FCC426396"; - - scoped_ptr<base::SymmetricKey> sym_key(base::SymmetricKey::Import( - base::SymmetricKey::AES, key)); - ASSERT_TRUE(NULL != sym_key.get()); - - base::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); - - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), - ciphertext.size())); -} - -TEST(EncryptorTest, EmptyDecrypt) { - std::string key = "128=SixteenBytes"; - std::string iv = "Sweet Sixteen IV"; - - scoped_ptr<base::SymmetricKey> sym_key(base::SymmetricKey::Import( - base::SymmetricKey::AES, key)); - ASSERT_TRUE(NULL != sym_key.get()); - - base::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); - - std::string decrypted; - EXPECT_FALSE(encryptor.Decrypt("", &decrypted)); - EXPECT_EQ("", decrypted); -} diff --git a/base/crypto/encryptor_win.cc b/base/crypto/encryptor_win.cc deleted file mode 100644 index 1d732b5..0000000 --- a/base/crypto/encryptor_win.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/crypto/encryptor.h" - -#include <vector> - -#include "base/crypto/symmetric_key.h" - -namespace base { - -namespace { - -// On success, returns the block size (in bytes) for the algorithm that |key| -// is for. On failure, returns 0. -DWORD GetCipherBlockSize(HCRYPTKEY key) { - DWORD block_size_in_bits = 0; - DWORD param_size = sizeof(block_size_in_bits); - BOOL ok = CryptGetKeyParam(key, KP_BLOCKLEN, - reinterpret_cast<BYTE*>(&block_size_in_bits), - ¶m_size, 0); - if (!ok) - return 0; - - return block_size_in_bits / 8; -} - -} // namespace - -Encryptor::Encryptor() - : key_(NULL), - mode_(CBC), - block_size_(0) { -} - -Encryptor::~Encryptor() { -} - -bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { - DCHECK(key); - DCHECK_EQ(CBC, mode) << "Unsupported mode of operation"; - - // In CryptoAPI, the IV, padding mode, and feedback register (for a chaining - // mode) are properties of a key, so we have to create a copy of the key for - // the Encryptor. See the Remarks section of the CryptEncrypt MSDN page. - BOOL ok = CryptDuplicateKey(key->key(), NULL, 0, capi_key_.receive()); - if (!ok) - return false; - - // CRYPT_MODE_CBC is the default for Microsoft Base Cryptographic Provider, - // but we set it anyway to be safe. - DWORD cipher_mode = CRYPT_MODE_CBC; - ok = CryptSetKeyParam(capi_key_.get(), KP_MODE, - reinterpret_cast<BYTE*>(&cipher_mode), 0); - if (!ok) - return false; - - block_size_ = GetCipherBlockSize(capi_key_.get()); - if (block_size_ == 0) - return false; - - if (iv.size() != block_size_) - return false; - - ok = CryptSetKeyParam(capi_key_.get(), KP_IV, - reinterpret_cast<const BYTE*>(iv.data()), 0); - if (!ok) - return false; - - DWORD padding_method = PKCS5_PADDING; - ok = CryptSetKeyParam(capi_key_.get(), KP_PADDING, - reinterpret_cast<BYTE*>(&padding_method), 0); - if (!ok) - return false; - - return true; -} - -bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { - DWORD data_len = plaintext.size(); - DWORD total_len = data_len + block_size_; - - // CryptoAPI encrypts/decrypts in place. - std::vector<BYTE> tmp(total_len); - memcpy(&tmp[0], plaintext.data(), data_len); - - BOOL ok = CryptEncrypt(capi_key_.get(), NULL, TRUE, 0, &tmp[0], - &data_len, total_len); - if (!ok) - return false; - - ciphertext->assign(reinterpret_cast<char*>(&tmp[0]), data_len); - return true; -} - -bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { - DWORD data_len = ciphertext.size(); - if (data_len == 0) - return false; - - std::vector<BYTE> tmp(data_len); - memcpy(&tmp[0], ciphertext.data(), data_len); - - BOOL ok = CryptDecrypt(capi_key_.get(), NULL, TRUE, 0, &tmp[0], &data_len); - if (!ok) - return false; - - DCHECK_GT(tmp.size(), data_len); - - plaintext->assign(reinterpret_cast<char*>(&tmp[0]), data_len); - return true; -} - -} // namespace base diff --git a/base/crypto/rsa_private_key.cc b/base/crypto/rsa_private_key.cc deleted file mode 100644 index 024f741..0000000 --- a/base/crypto/rsa_private_key.cc +++ /dev/null @@ -1,390 +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/crypto/rsa_private_key.h" - -#include <algorithm> -#include <list> - -#include "base/logging.h" -#include "base/scoped_ptr.h" -#include "base/string_util.h" - -// This file manually encodes and decodes RSA private keys using PrivateKeyInfo -// from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are: -// -// PrivateKeyInfo ::= SEQUENCE { -// version Version, -// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, -// privateKey PrivateKey, -// attributes [0] IMPLICIT Attributes OPTIONAL -// } -// -// RSAPrivateKey ::= SEQUENCE { -// version Version, -// modulus INTEGER, -// publicExponent INTEGER, -// privateExponent INTEGER, -// prime1 INTEGER, -// prime2 INTEGER, -// exponent1 INTEGER, -// exponent2 INTEGER, -// coefficient INTEGER -// } - -namespace { -// Helper for error handling during key import. -#define READ_ASSERT(truth) \ - if (!(truth)) { \ - NOTREACHED(); \ - return false; \ - } -} // namespace - -namespace base { - -const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00 -}; - -PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) - : big_endian_(big_endian) {} - -PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {} - -bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) { - std::list<uint8> content; - - // Version (always zero) - uint8 version = 0; - - PrependInteger(coefficient_, &content); - PrependInteger(exponent2_, &content); - PrependInteger(exponent1_, &content); - PrependInteger(prime2_, &content); - PrependInteger(prime1_, &content); - PrependInteger(private_exponent_, &content); - PrependInteger(public_exponent_, &content); - PrependInteger(modulus_, &content); - PrependInteger(&version, 1, &content); - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content); - - // RSA algorithm OID - for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) - content.push_front(kRsaAlgorithmIdentifier[i - 1]); - - PrependInteger(&version, 1, &content); - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - - // Copy everying into the output. - output->reserve(content.size()); - for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) - output->push_back(*i); - - return true; -} - -bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) { - // Create a sequence with the modulus (n) and public exponent (e). - std::vector<uint8> bit_string; - if (!ExportPublicKey(&bit_string)) - return false; - - // Add the sequence as the contents of a bit string. - std::list<uint8> content; - PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()), - &content); - - // Add the RSA algorithm OID. - for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) - content.push_front(kRsaAlgorithmIdentifier[i - 1]); - - // Finally, wrap everything in a sequence. - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - - // Copy everything into the output. - output->reserve(content.size()); - for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) - output->push_back(*i); - - return true; -} - -bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8>* output) { - // Create a sequence with the modulus (n) and public exponent (e). - std::list<uint8> content; - PrependInteger(&public_exponent_[0], - static_cast<int>(public_exponent_.size()), - &content); - PrependInteger(&modulus_[0], static_cast<int>(modulus_.size()), &content); - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - - // Copy everything into the output. - output->reserve(content.size()); - for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) - output->push_back(*i); - - return true; -} - -bool PrivateKeyInfoCodec::Import(const std::vector<uint8>& input) { - if (input.empty()) { - return false; - } - - // Parse the private key info up to the public key values, ignoring - // the subsequent private key values. - uint8* src = const_cast<uint8*>(&input.front()); - uint8* end = src + input.size(); - if (!ReadSequence(&src, end) || - !ReadVersion(&src, end) || - !ReadAlgorithmIdentifier(&src, end) || - !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) || - !ReadSequence(&src, end) || - !ReadVersion(&src, end) || - !ReadInteger(&src, end, &modulus_)) - return false; - - int mod_size = modulus_.size(); - READ_ASSERT(mod_size % 2 == 0); - int primes_size = mod_size / 2; - - if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) || - !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_)) - return false; - - READ_ASSERT(src == end); - - - return true; -} - -void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8>& in, - std::list<uint8>* out) { - uint8* ptr = const_cast<uint8*>(&in.front()); - PrependIntegerImpl(ptr, in.size(), out, big_endian_); -} - -// Helper to prepend an ASN.1 integer. -void PrivateKeyInfoCodec::PrependInteger(uint8* val, - int num_bytes, - std::list<uint8>* data) { - PrependIntegerImpl(val, num_bytes, data, big_endian_); -} - -void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val, - int num_bytes, - std::list<uint8>* data, - bool big_endian) { - // Reverse input if little-endian. - std::vector<uint8> tmp; - if (!big_endian) { - tmp.assign(val, val + num_bytes); - reverse(tmp.begin(), tmp.end()); - val = &tmp.front(); - } - - // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes - // from the most-significant end of the integer. - int start = 0; - while (start < (num_bytes - 1) && val[start] == 0x00) { - start++; - num_bytes--; - } - PrependBytes(val, start, num_bytes, data); - - // ASN.1 integers are signed. To encode a positive integer whose sign bit - // (the most significant bit) would otherwise be set and make the number - // negative, ASN.1 requires a leading null byte to force the integer to be - // positive. - uint8 front = data->front(); - if ((front & 0x80) != 0) { - data->push_front(0x00); - num_bytes++; - } - - PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); -} - -bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, - uint8* end, - std::vector<uint8>* out) { - return ReadIntegerImpl(pos, end, out, big_endian_); -} - -bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, - uint8* end, - size_t expected_size, - std::vector<uint8>* out) { - std::vector<uint8> temp; - if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian - return false; - - int pad = expected_size - temp.size(); - int index = 0; - if (out->size() == expected_size + 1) { - READ_ASSERT(out->front() == 0x00); - pad++; - index++; - } else { - READ_ASSERT(out->size() <= expected_size); - } - - while (pad) { - out->push_back(0x00); - pad--; - } - out->insert(out->end(), temp.begin(), temp.end()); - - // Reverse output if little-endian. - if (!big_endian_) - reverse(out->begin(), out->end()); - return true; -} - -bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, - uint8* end, - std::vector<uint8>* out, - bool big_endian) { - uint32 length = 0; - if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length) - return false; - - // The first byte can be zero to force positiveness. We can ignore this. - if (**pos == 0x00) { - ++(*pos); - --length; - } - - if (length) - out->insert(out->end(), *pos, (*pos) + length); - - (*pos) += length; - - // Reverse output if little-endian. - if (!big_endian) - reverse(out->begin(), out->end()); - return true; -} - -void PrivateKeyInfoCodec::PrependBytes(uint8* val, - int start, - int num_bytes, - std::list<uint8>* data) { - while (num_bytes > 0) { - --num_bytes; - data->push_front(val[start + num_bytes]); - } -} - -void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8>* data) { - // The high bit is used to indicate whether additional octets are needed to - // represent the length. - if (size < 0x80) { - data->push_front(static_cast<uint8>(size)); - } else { - uint8 num_bytes = 0; - while (size > 0) { - data->push_front(static_cast<uint8>(size & 0xFF)); - size >>= 8; - num_bytes++; - } - CHECK_LE(num_bytes, 4); - data->push_front(0x80 | num_bytes); - } -} - -void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, - uint32 length, - std::list<uint8>* output) { - PrependLength(length, output); - output->push_front(type); -} - -void PrivateKeyInfoCodec::PrependBitString(uint8* val, - int num_bytes, - std::list<uint8>* output) { - // Start with the data. - PrependBytes(val, 0, num_bytes, output); - // Zero unused bits. - output->push_front(0); - // Add the length. - PrependLength(num_bytes + 1, output); - // Finally, add the bit string tag. - output->push_front((uint8) kBitStringTag); -} - -bool PrivateKeyInfoCodec::ReadLength(uint8** pos, uint8* end, uint32* result) { - READ_ASSERT(*pos < end); - int length = 0; - - // If the MSB is not set, the length is just the byte itself. - if (!(**pos & 0x80)) { - length = **pos; - (*pos)++; - } else { - // Otherwise, the lower 7 indicate the length of the length. - int length_of_length = **pos & 0x7F; - READ_ASSERT(length_of_length <= 4); - (*pos)++; - READ_ASSERT(*pos + length_of_length < end); - - length = 0; - for (int i = 0; i < length_of_length; ++i) { - length <<= 8; - length |= **pos; - (*pos)++; - } - } - - READ_ASSERT(*pos + length <= end); - if (result) *result = length; - return true; -} - -bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8** pos, - uint8* end, - uint8 expected_tag, - uint32* length) { - READ_ASSERT(*pos < end); - READ_ASSERT(**pos == expected_tag); - (*pos)++; - - return ReadLength(pos, end, length); -} - -bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { - return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); -} - -bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { - READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); - READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, - sizeof(kRsaAlgorithmIdentifier)) == 0); - (*pos) += sizeof(kRsaAlgorithmIdentifier); - return true; -} - -bool PrivateKeyInfoCodec::ReadVersion(uint8** pos, uint8* end) { - uint32 length = 0; - if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length)) - return false; - - // The version should be zero. - for (uint32 i = 0; i < length; ++i) { - READ_ASSERT(**pos == 0x00); - (*pos)++; - } - - return true; -} - -} // namespace base diff --git a/base/crypto/rsa_private_key.h b/base/crypto/rsa_private_key.h deleted file mode 100644 index 5357adc..0000000 --- a/base/crypto/rsa_private_key.h +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CRYPTO_RSA_PRIVATE_KEY_H_ -#define BASE_CRYPTO_RSA_PRIVATE_KEY_H_ -#pragma once - -#include "build/build_config.h" - -#if defined(USE_OPENSSL) -// Forward declaration for openssl/*.h -typedef struct evp_pkey_st EVP_PKEY; -#elif defined(USE_NSS) -// Forward declaration. -struct SECKEYPrivateKeyStr; -struct SECKEYPublicKeyStr; -#elif defined(OS_MACOSX) -#include <Security/cssm.h> -#endif - -#include <list> -#include <vector> - -#include "base/basictypes.h" - -#if defined(OS_WIN) -#include "base/crypto/scoped_capi_types.h" -#endif -#if defined(USE_NSS) -#include "base/gtest_prod_util.h" -#endif - -namespace base { - -// Used internally by RSAPrivateKey for serializing and deserializing -// PKCS #8 PrivateKeyInfo and PublicKeyInfo. -class PrivateKeyInfoCodec { - public: - - // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8. - static const uint8 kRsaAlgorithmIdentifier[]; - - // ASN.1 tags for some types we use. - static const uint8 kBitStringTag = 0x03; - static const uint8 kIntegerTag = 0x02; - static const uint8 kNullTag = 0x05; - static const uint8 kOctetStringTag = 0x04; - static const uint8 kSequenceTag = 0x30; - - // |big_endian| here specifies the byte-significance of the integer components - // that will be parsed & serialized (modulus(), etc...) during Import(), - // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the - // PrivateKeyInfo/PublicKeyInfo (which is always big-endian). - explicit PrivateKeyInfoCodec(bool big_endian); - - ~PrivateKeyInfoCodec(); - - // Exports the contents of the integer components to the ASN.1 DER encoding - // of the PrivateKeyInfo structure to |output|. - bool Export(std::vector<uint8>* output); - - // Exports the contents of the integer components to the ASN.1 DER encoding - // of the PublicKeyInfo structure to |output|. - bool ExportPublicKeyInfo(std::vector<uint8>* output); - - // Exports the contents of the integer components to the ASN.1 DER encoding - // of the RSAPublicKey structure to |output|. - bool ExportPublicKey(std::vector<uint8>* output); - - // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input| - // and populates the integer components with |big_endian_| byte-significance. - // IMPORTANT NOTE: This is currently *not* security-approved for importing - // keys from unstrusted sources. - bool Import(const std::vector<uint8>& input); - - // Accessors to the contents of the integer components of the PrivateKeyInfo - // structure. - std::vector<uint8>* modulus() { return &modulus_; }; - std::vector<uint8>* public_exponent() { return &public_exponent_; }; - std::vector<uint8>* private_exponent() { return &private_exponent_; }; - std::vector<uint8>* prime1() { return &prime1_; }; - std::vector<uint8>* prime2() { return &prime2_; }; - std::vector<uint8>* exponent1() { return &exponent1_; }; - std::vector<uint8>* exponent2() { return &exponent2_; }; - std::vector<uint8>* coefficient() { return &coefficient_; }; - - private: - // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_| - // value. - void PrependInteger(const std::vector<uint8>& in, std::list<uint8>* out); - void PrependInteger(uint8* val, int num_bytes, std::list<uint8>* data); - - // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian| - // byte-significance into |data| as an ASN.1 integer. - void PrependIntegerImpl(uint8* val, - int num_bytes, - std::list<uint8>* data, - bool big_endian); - - // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_| - // value. - bool ReadInteger(uint8** pos, uint8* end, std::vector<uint8>* out); - bool ReadIntegerWithExpectedSize(uint8** pos, - uint8* end, - size_t expected_size, - std::vector<uint8>* out); - - // Reads an ASN.1 integer from |pos|, and stores the result into |out| with - // |big_endian| byte-significance. - bool ReadIntegerImpl(uint8** pos, - uint8* end, - std::vector<uint8>* out, - bool big_endian); - - // Prepends the integer stored in |val|, starting a index |start|, for - // |num_bytes| bytes onto |data|. - void PrependBytes(uint8* val, - int start, - int num_bytes, - std::list<uint8>* data); - - // Helper to prepend an ASN.1 length field. - void PrependLength(size_t size, std::list<uint8>* data); - - // Helper to prepend an ASN.1 type header. - void PrependTypeHeaderAndLength(uint8 type, - uint32 length, - std::list<uint8>* output); - - // Helper to prepend an ASN.1 bit string - void PrependBitString(uint8* val, int num_bytes, std::list<uint8>* output); - - // Read an ASN.1 length field. This also checks that the length does not - // extend beyond |end|. - bool ReadLength(uint8** pos, uint8* end, uint32* result); - - // Read an ASN.1 type header and its length. - bool ReadTypeHeaderAndLength(uint8** pos, - uint8* end, - uint8 expected_tag, - uint32* length); - - // Read an ASN.1 sequence declaration. This consumes the type header and - // length field, but not the contents of the sequence. - bool ReadSequence(uint8** pos, uint8* end); - - // Read the RSA AlgorithmIdentifier. - bool ReadAlgorithmIdentifier(uint8** pos, uint8* end); - - // Read one of the two version fields in PrivateKeyInfo. - bool ReadVersion(uint8** pos, uint8* end); - - // The byte-significance of the stored components (modulus, etc..). - bool big_endian_; - - // Component integers of the PrivateKeyInfo - std::vector<uint8> modulus_; - std::vector<uint8> public_exponent_; - std::vector<uint8> private_exponent_; - std::vector<uint8> prime1_; - std::vector<uint8> prime2_; - std::vector<uint8> exponent1_; - std::vector<uint8> exponent2_; - std::vector<uint8> coefficient_; - - DISALLOW_COPY_AND_ASSIGN(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: - ~RSAPrivateKey(); - - // Create a new random instance. Can return NULL if initialization fails. - static RSAPrivateKey* Create(uint16 num_bits); - - // Create a new random instance. Can return NULL if initialization fails. - // The created key is permanent and is not exportable in plaintext form. - // - // NOTE: Currently only available if USE_NSS is defined. - static RSAPrivateKey* CreateSensitive(uint16 num_bits); - - // Create a new instance by importing an existing private key. The format is - // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if - // initialization fails. - static RSAPrivateKey* CreateFromPrivateKeyInfo( - const std::vector<uint8>& input); - - // Create a new instance by importing an existing private key. The format is - // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if - // initialization fails. - // The created key is permanent and is not exportable in plaintext form. - // - // NOTE: Currently only available if USE_NSS is defined. - static RSAPrivateKey* CreateSensitiveFromPrivateKeyInfo( - const std::vector<uint8>& input); - - // Import an existing public key, and then search for the private - // half in the key database. The format of the public key blob is is - // an X509 SubjectPublicKeyInfo block. This can return NULL if - // initialization fails or the private key cannot be found. The - // caller takes ownership of the returned object, but nothing new is - // created in the key database. - // - // NOTE: Currently only available if USE_NSS is defined. - static RSAPrivateKey* FindFromPublicKeyInfo( - const std::vector<uint8>& input); - -#if defined(USE_OPENSSL) - 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_; } -#elif defined(OS_MACOSX) - CSSM_KEY_PTR key() { return &key_; } - CSSM_KEY_PTR public_key() { return &public_key_; } -#endif - - // Exports the private key to a PKCS #1 PrivateKey block. - bool ExportPrivateKey(std::vector<uint8>* output); - - // Exports the public key to an X509 SubjectPublicKeyInfo block. - bool ExportPublicKey(std::vector<uint8>* output); - - private: -#if defined(USE_NSS) - FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FindFromPublicKey); - FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FailedFindFromPublicKey); -#endif - - // Constructor is private. Use one of the Create*() or Find*() - // methods above instead. - RSAPrivateKey(); - - // Shared helper for Create() and CreateSensitive(). - // TODO(cmasone): consider replacing |permanent| and |sensitive| with a - // flags arg created by ORing together some enumerated values. - static RSAPrivateKey* CreateWithParams(uint16 num_bits, - bool permanent, - bool sensitive); - - // Shared helper for CreateFromPrivateKeyInfo() and - // CreateSensitiveFromPrivateKeyInfo(). - static RSAPrivateKey* CreateFromPrivateKeyInfoWithParams( - const std::vector<uint8>& input, bool permanent, bool sensitive); - -#if defined(USE_OPENSSL) - EVP_PKEY* key_; -#elif defined(USE_NSS) - SECKEYPrivateKeyStr* key_; - SECKEYPublicKeyStr* public_key_; -#elif defined(OS_WIN) - bool InitProvider(); - - ScopedHCRYPTPROV provider_; - ScopedHCRYPTKEY key_; -#elif defined(OS_MACOSX) - CSSM_KEY key_; - CSSM_KEY public_key_; -#endif - - DISALLOW_COPY_AND_ASSIGN(RSAPrivateKey); -}; - -} // namespace base - -#endif // BASE_CRYPTO_RSA_PRIVATE_KEY_H_ diff --git a/base/crypto/rsa_private_key_mac.cc b/base/crypto/rsa_private_key_mac.cc deleted file mode 100644 index ede8014..0000000 --- a/base/crypto/rsa_private_key_mac.cc +++ /dev/null @@ -1,196 +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/crypto/rsa_private_key.h" - -#include <list> - -#include "base/crypto/cssm_init.h" -#include "base/logging.h" -#include "base/scoped_ptr.h" - -namespace base { - -// static -RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - - CSSM_CC_HANDLE cc_handle; - CSSM_RETURN crtn; - crtn = CSSM_CSP_CreateKeyGenContext(GetSharedCSPHandle(), CSSM_ALGID_RSA, - num_bits, NULL, NULL, NULL, NULL, NULL, - &cc_handle); - if (crtn) { - NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; - return NULL; - } - - CSSM_DATA label = { 9, - const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) }; - crtn = CSSM_GenerateKeyPair(cc_handle, - CSSM_KEYUSE_VERIFY, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, - result->public_key(), CSSM_KEYUSE_SIGN, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL, - result->key()); - CSSM_DeleteContext(cc_handle); - if (crtn) { - NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; - return NULL; - } - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { - NOTIMPLEMENTED(); - return NULL; -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( - const std::vector<uint8>& input) { - if (input.empty()) - return NULL; - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - - CSSM_KEY key; - memset(&key, 0, sizeof(key)); - key.KeyData.Data = const_cast<uint8*>(&input.front()); - key.KeyData.Length = input.size(); - key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; - key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; - key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW; - key.KeyHeader.AlgorithmId = CSSM_ALGID_RSA; - key.KeyHeader.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; - key.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; - key.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; - - CSSM_KEY_SIZE key_size; - CSSM_RETURN crtn; - crtn = CSSM_QueryKeySizeInBits(GetSharedCSPHandle(), NULL, &key, &key_size); - if (crtn) { - NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn; - return NULL; - } - key.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits; - - // Perform a NULL unwrap operation on the key so that result's key_ - // instance variable points to a key that can be released via CSSM_FreeKey(). - CSSM_ACCESS_CREDENTIALS creds; - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - CSSM_CC_HANDLE cc_handle; - crtn = CSSM_CSP_CreateSymmetricContext(GetSharedCSPHandle(), CSSM_ALGID_NONE, - CSSM_ALGMODE_NONE, &creds, NULL, NULL, CSSM_PADDING_NONE, 0, &cc_handle); - if (crtn) { - NOTREACHED() << "CSSM_CSP_CreateSymmetricContext failed: " << crtn; - return NULL; - } - CSSM_DATA label_data, desc_data = { 0, NULL }; - label_data.Data = - const_cast<uint8*>(reinterpret_cast<const uint8*>("unwrapped")); - label_data.Length = 9; - crtn = CSSM_UnwrapKey(cc_handle, NULL, &key, CSSM_KEYUSE_ANY, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label_data, - NULL, result->key(), &desc_data); - if (crtn) { - NOTREACHED() << "CSSM_UnwrapKey failed: " << crtn; - return NULL; - } - - // Extract a public key from the private key. - // Apple doesn't accept CSSM_KEYBLOB_RAW_FORMAT_X509 as a valid key - // format when attempting to generate certs, so use PKCS1 instead. - PrivateKeyInfoCodec codec(true); - std::vector<uint8> private_key_data; - private_key_data.assign(key.KeyData.Data, - key.KeyData.Data + key.KeyData.Length); - if (!codec.Import(private_key_data)) { - return NULL; - } - std::vector<uint8> public_key_data; - if (!codec.ExportPublicKey(&public_key_data)) { - return NULL; - } - - CSSM_KEY* public_key = result->public_key(); - size_t size = public_key_data.size(); - public_key->KeyData.Data = reinterpret_cast<uint8*>(CSSMMalloc(size)); - if (!public_key->KeyData.Data) { - NOTREACHED() << "CSSMMalloc failed"; - return NULL; - } - memcpy(public_key->KeyData.Data, &public_key_data.front(), size); - public_key->KeyData.Length = size; - public_key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; - public_key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; - public_key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW; - public_key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA; - public_key->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; - public_key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; - public_key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; - - crtn = CSSM_QueryKeySizeInBits( - base::GetSharedCSPHandle(), NULL, public_key, &key_size); - if (crtn) { - DLOG(ERROR) << "CSSM_QueryKeySizeInBits failed " << crtn; - return NULL; - } - public_key->KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( - const std::vector<uint8>& input) { - NOTIMPLEMENTED(); - return NULL; -} - -// static -RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( - const std::vector<uint8>& input) { - NOTIMPLEMENTED(); - return NULL; -} - -RSAPrivateKey::RSAPrivateKey() { - memset(&key_, 0, sizeof(key_)); - memset(&public_key_, 0, sizeof(public_key_)); - - EnsureCSSMInit(); -} - -RSAPrivateKey::~RSAPrivateKey() { - if (key_.KeyData.Data) { - CSSM_FreeKey(GetSharedCSPHandle(), NULL, &key_, CSSM_FALSE); - } - if (public_key_.KeyData.Data) { - CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key_, CSSM_FALSE); - } -} - -bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { - if (!key_.KeyData.Data || !key_.KeyData.Length) { - return false; - } - output->clear(); - output->insert(output->end(), key_.KeyData.Data, - key_.KeyData.Data + key_.KeyData.Length); - return true; -} - -bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { - PrivateKeyInfoCodec private_key_info(true); - std::vector<uint8> private_key_data; - private_key_data.assign(key_.KeyData.Data, - key_.KeyData.Data + key_.KeyData.Length); - return (private_key_info.Import(private_key_data) && - private_key_info.ExportPublicKeyInfo(output)); -} - -} // namespace base diff --git a/base/crypto/rsa_private_key_nss.cc b/base/crypto/rsa_private_key_nss.cc deleted file mode 100644 index 202aa1d..0000000 --- a/base/crypto/rsa_private_key_nss.cc +++ /dev/null @@ -1,248 +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/crypto/rsa_private_key.h" - -#include <cryptohi.h> -#include <keyhi.h> -#include <pk11pub.h> - -#include <list> - -#include "base/debug/leak_annotations.h" -#include "base/logging.h" -#include "base/nss_util.h" -#include "base/nss_util_internal.h" -#include "base/scoped_ptr.h" -#include "base/string_util.h" - -// TODO(rafaelw): Consider refactoring common functions and definitions from -// rsa_private_key_win.cc or using NSS's ASN.1 encoder. -namespace { - -static bool ReadAttribute(SECKEYPrivateKey* key, - CK_ATTRIBUTE_TYPE type, - std::vector<uint8>* output) { - SECItem item; - SECStatus rv; - rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - - output->assign(item.data, item.data + item.len); - SECITEM_FreeItem(&item, PR_FALSE); - return true; -} - -} // namespace - -namespace base { - -RSAPrivateKey::~RSAPrivateKey() { - if (key_) - SECKEY_DestroyPrivateKey(key_); - if (public_key_) - SECKEY_DestroyPublicKey(public_key_); -} - -// static -RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { - return CreateWithParams(num_bits, - PR_FALSE /* not permanent */, - PR_FALSE /* not sensitive */); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { - return CreateWithParams(num_bits, - PR_TRUE /* permanent */, - PR_TRUE /* sensitive */); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( - const std::vector<uint8>& input) { - return CreateFromPrivateKeyInfoWithParams(input, - PR_FALSE /* not permanent */, - PR_FALSE /* not sensitive */); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( - const std::vector<uint8>& input) { - return CreateFromPrivateKeyInfoWithParams(input, - PR_TRUE /* permanent */, - PR_TRUE /* seneitive */); -} - -// static -RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( - const std::vector<uint8>& input) { - base::EnsureNSSInit(); - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - - // First, decode and save the public key. - SECItem key_der; - key_der.type = siBuffer; - key_der.data = const_cast<unsigned char*>(&input[0]); - key_der.len = input.size(); - - CERTSubjectPublicKeyInfo *spki = - SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); - if (!spki) { - NOTREACHED(); - return NULL; - } - - result->public_key_ = SECKEY_ExtractPublicKey(spki); - SECKEY_DestroySubjectPublicKeyInfo(spki); - if (!result->public_key_) { - NOTREACHED(); - return NULL; - } - - // Now, look for the associated private key in the user's NSS DB. If it's - // not there, consider that an error. - PK11SlotInfo *slot = GetDefaultNSSKeySlot(); - if (!slot) { - NOTREACHED(); - return NULL; - } - - // Make sure the key is an RSA key. If not, that's an error - if (result->public_key_->keyType != rsaKey) { - PK11_FreeSlot(slot); - NOTREACHED(); - return NULL; - } - - SECItem *ck_id = PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)); - if (!ck_id) { - PK11_FreeSlot(slot); - NOTREACHED(); - return NULL; - } - - // Finally...Look for the key! - result->key_ = PK11_FindKeyByKeyID(slot, ck_id, NULL); - - // Cleanup... - PK11_FreeSlot(slot); - SECITEM_FreeItem(ck_id, PR_TRUE); - - // If we didn't find it, that's ok. - if (!result->key_) - return NULL; - - return result.release(); -} - - -bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { - PrivateKeyInfoCodec private_key_info(true); - - // Manually read the component attributes of the private key and build up - // the PrivateKeyInfo. - if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) || - !ReadAttribute(key_, CKA_PUBLIC_EXPONENT, - private_key_info.public_exponent()) || - !ReadAttribute(key_, CKA_PRIVATE_EXPONENT, - private_key_info.private_exponent()) || - !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) || - !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) || - !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) || - !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || - !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { - NOTREACHED(); - return false; - } - - return private_key_info.Export(output); -} - -bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { - SECItem* der_pubkey = SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_); - if (!der_pubkey) { - NOTREACHED(); - return false; - } - - for (size_t i = 0; i < der_pubkey->len; ++i) - output->push_back(der_pubkey->data[i]); - - SECITEM_FreeItem(der_pubkey, PR_TRUE); - return true; -} - -RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { - EnsureNSSInit(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits, - bool permanent, - bool sensitive) { - base::EnsureNSSInit(); - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - - PK11SlotInfo *slot = GetDefaultNSSKeySlot(); - if (!slot) - return NULL; - - PK11RSAGenParams param; - param.keySizeInBits = num_bits; - param.pe = 65537L; - result->key_ = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶m, - &result->public_key_, permanent, sensitive, NULL); - PK11_FreeSlot(slot); - if (!result->key_) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( - const std::vector<uint8>& input, bool permanent, bool sensitive) { - // This method currently leaks some memory. - // See http://crbug.com/34742. - ANNOTATE_SCOPED_MEMORY_LEAK; - base::EnsureNSSInit(); - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - - PK11SlotInfo *slot = GetDefaultNSSKeySlot(); - if (!slot) - return NULL; - - SECItem der_private_key_info; - der_private_key_info.data = const_cast<unsigned char*>(&input.front()); - der_private_key_info.len = input.size(); - // Allow the private key to be used for key unwrapping, data decryption, - // and signature generation. - const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | - KU_DIGITAL_SIGNATURE; - SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( - slot, &der_private_key_info, NULL, NULL, permanent, sensitive, - key_usage, &result->key_, NULL); - PK11_FreeSlot(slot); - if (rv != SECSuccess) { - NOTREACHED(); - return NULL; - } - - result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); - if (!result->public_key_) { - NOTREACHED(); - return NULL; - } - - return result.release(); -} - -} // namespace base diff --git a/base/crypto/rsa_private_key_nss_unittest.cc b/base/crypto/rsa_private_key_nss_unittest.cc deleted file mode 100644 index 7dbe628..0000000 --- a/base/crypto/rsa_private_key_nss_unittest.cc +++ /dev/null @@ -1,64 +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/crypto/rsa_private_key.h" - -#include <keyhi.h> -#include <pk11pub.h> - -#include "base/nss_util.h" -#include "base/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { - -class RSAPrivateKeyNSSTest : public testing::Test { - public: - RSAPrivateKeyNSSTest() {} - virtual ~RSAPrivateKeyNSSTest() {} - - virtual void SetUp() { -#if defined(OS_CHROMEOS) - base::OpenPersistentNSSDB(); -#endif - } - - private: - DISALLOW_COPY_AND_ASSIGN(RSAPrivateKeyNSSTest); -}; - -TEST_F(RSAPrivateKeyNSSTest, FindFromPublicKey) { - // Create a keypair, which will put the keys in the user's NSSDB. - scoped_ptr<base::RSAPrivateKey> key_pair(base::RSAPrivateKey::Create(256)); - - std::vector<uint8> public_key; - ASSERT_TRUE(key_pair->ExportPublicKey(&public_key)); - - scoped_ptr<base::RSAPrivateKey> key_pair_2( - base::RSAPrivateKey::FindFromPublicKeyInfo(public_key)); - - EXPECT_EQ(key_pair->key_->pkcs11ID, key_pair_2->key_->pkcs11ID); -} - -TEST_F(RSAPrivateKeyNSSTest, FailedFindFromPublicKey) { - // Create a keypair, which will put the keys in the user's NSSDB. - scoped_ptr<base::RSAPrivateKey> key_pair(base::RSAPrivateKey::Create(256)); - - std::vector<uint8> public_key; - ASSERT_TRUE(key_pair->ExportPublicKey(&public_key)); - - // Remove the keys from the DB, and make sure we can't find them again. - if (key_pair->key_) { - PK11_DestroyTokenObject(key_pair->key_->pkcs11Slot, - key_pair->key_->pkcs11ID); - } - if (key_pair->public_key_) { - PK11_DestroyTokenObject(key_pair->public_key_->pkcs11Slot, - key_pair->public_key_->pkcs11ID); - } - - EXPECT_EQ(NULL, base::RSAPrivateKey::FindFromPublicKeyInfo(public_key)); -} - -} // namespace base diff --git a/base/crypto/rsa_private_key_openssl.cc b/base/crypto/rsa_private_key_openssl.cc deleted file mode 100644 index 891ea52..0000000 --- a/base/crypto/rsa_private_key_openssl.cc +++ /dev/null @@ -1,135 +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/crypto/rsa_private_key.h" - -#include <openssl/evp.h> -#include <openssl/pkcs12.h> -#include <openssl/rsa.h> - -#include "base/logging.h" -#include "base/openssl_util.h" -#include "base/scoped_ptr.h" -#include "base/stl_util-inl.h" - -namespace base { - -namespace { - -// Function pointer definition, for injecting the required key export function -// into ExportKey, below. The supplied function should export EVP_PKEY into -// the supplied BIO, returning 1 on success or 0 on failure. -typedef int (ExportFunction)(BIO*, EVP_PKEY*); - -// Helper to export |key| into |output| via the specified ExportFunction. -bool ExportKey(EVP_PKEY* key, - ExportFunction export_fn, - std::vector<uint8>* output) { - if (!key) - return false; - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem())); - - int res = export_fn(bio.get(), key); - if (!res) - return false; - - char* data = NULL; - long len = BIO_get_mem_data(bio.get(), &data); - if (!data || len < 0) - return false; - - STLAssignToVector(output, reinterpret_cast<const uint8*>(data), len); - return true; -} - -} // namespace - -// static -RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - 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); - result->key_ = EVP_PKEY_new(); - if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get())) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { - NOTIMPLEMENTED(); - return NULL; -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( - const std::vector<uint8>& input) { - 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*>( - vector_as_array(&input))); - ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, input.size())); - if (!bio.get()) - return NULL; - - // Importing is a little more involved than exporting, as we must first - // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key - // Info structure returned. - ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8inf( - d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL)); - if (!p8inf.get()) - return NULL; - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - result->key_ = EVP_PKCS82PKEY(p8inf.get()); - if (!result->key_) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( - const std::vector<uint8>& input) { - NOTIMPLEMENTED(); - return NULL; -} - -// static -RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( - const std::vector<uint8>& input) { - NOTIMPLEMENTED(); - return NULL; -} - -RSAPrivateKey::RSAPrivateKey() - : key_(NULL) { -} - -RSAPrivateKey::~RSAPrivateKey() { - if (key_) - EVP_PKEY_free(key_); -} - -bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { - return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output); -} - -bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { - return ExportKey(key_, i2d_PUBKEY_bio, output); -} - -} // namespace base diff --git a/base/crypto/rsa_private_key_unittest.cc b/base/crypto/rsa_private_key_unittest.cc deleted file mode 100644 index 3b0d846..0000000 --- a/base/crypto/rsa_private_key_unittest.cc +++ /dev/null @@ -1,383 +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/crypto/rsa_private_key.h" -#include "base/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -// Generate random private keys with two different sizes. Reimport, then -// export them again. We should get back the same exact bytes. -TEST(RSAPrivateKeyUnitTest, InitRandomTest) { - scoped_ptr<base::RSAPrivateKey> keypair1(base::RSAPrivateKey::Create(1024)); - scoped_ptr<base::RSAPrivateKey> keypair2(base::RSAPrivateKey::Create(2048)); - ASSERT_TRUE(keypair1.get()); - ASSERT_TRUE(keypair2.get()); - - std::vector<uint8> privkey1; - std::vector<uint8> privkey2; - std::vector<uint8> pubkey1; - std::vector<uint8> pubkey2; - - ASSERT_TRUE(keypair1->ExportPrivateKey(&privkey1)); - ASSERT_TRUE(keypair2->ExportPrivateKey(&privkey2)); - ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1)); - ASSERT_TRUE(keypair2->ExportPublicKey(&pubkey2)); - - scoped_ptr<base::RSAPrivateKey> keypair3( - base::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey1)); - scoped_ptr<base::RSAPrivateKey> keypair4( - base::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey2)); - ASSERT_TRUE(keypair3.get()); - ASSERT_TRUE(keypair4.get()); - - std::vector<uint8> privkey3; - std::vector<uint8> privkey4; - ASSERT_TRUE(keypair3->ExportPrivateKey(&privkey3)); - ASSERT_TRUE(keypair4->ExportPrivateKey(&privkey4)); - - ASSERT_EQ(privkey1.size(), privkey3.size()); - ASSERT_EQ(privkey2.size(), privkey4.size()); - ASSERT_TRUE(0 == memcmp(&privkey1.front(), &privkey3.front(), - privkey1.size())); - ASSERT_TRUE(0 == memcmp(&privkey2.front(), &privkey4.front(), - privkey2.size())); -} - - -// Verify that generated public keys look good. This test data was generated -// with the openssl command line tool. -TEST(RSAPrivateKeyUnitTest, PublicKeyTest) { - const uint8 private_key_info[] = { - 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, - 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, - 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, - 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, - 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, - 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, - 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, - 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, - 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, - 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, - 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, - 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, - 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, - 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, - 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, - 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, - 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, - 0x37, 0xcb, 0xf2, 0x98, 0xa0, 0xce, 0xb4, 0xcb, - 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7, - 0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, - 0xed, 0xb8, 0x48, 0x8b, 0x16, 0x93, 0x36, 0x95, - 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6, - 0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, - 0x43, 0x78, 0xf9, 0xfe, 0x1f, 0x33, 0x23, 0x1e, - 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b, - 0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, - 0x86, 0xb2, 0xcb, 0x3c, 0xfe, 0x4e, 0xa1, 0xfa, - 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38, - 0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, - 0xa3, 0xf6, 0x85, 0x6b, 0x84, 0x43, 0xc9, 0x1e, - 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e, - 0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, - 0x29, 0x5c, 0xc0, 0x4f, 0x01, 0x02, 0x41, 0x00, - 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c, - 0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, - 0xcc, 0x61, 0xcd, 0x38, 0x42, 0x20, 0xd3, 0x82, - 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89, - 0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, - 0xba, 0x16, 0x1a, 0xea, 0x15, 0xc6, 0xf0, 0xb8, - 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2, - 0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, - 0x02, 0x41, 0x00, 0xc0, 0x60, 0x62, 0x80, 0xe1, - 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72, - 0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, - 0x7d, 0xd6, 0xb8, 0x31, 0x2b, 0x84, 0x7f, 0x62, - 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c, - 0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, - 0x5c, 0x09, 0x3c, 0xcf, 0x2f, 0x44, 0x9d, 0xb6, - 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b, - 0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, - 0xe2, 0x0e, 0x56, 0xca, 0x03, 0x1a, 0xc0, 0xf9, - 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda, - 0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, - 0xda, 0x55, 0x98, 0x74, 0xfc, 0x28, 0x17, 0x93, - 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae, - 0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, - 0xb8, 0x06, 0x03, 0xba, 0x08, 0x59, 0x2b, 0x17, - 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41, - 0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, - 0xa0, 0x24, 0xf5, 0xdb, 0x2f, 0xf0, 0x2f, 0xf1, - 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0, - 0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, - 0xb4, 0x14, 0xd4, 0x09, 0x91, 0x33, 0x5a, 0xfd, - 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69, - 0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, - 0xff, 0x6e, 0xeb, 0xc6, 0x86, 0xf5, 0xb4, 0xc7, - 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f, - 0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, - 0x3e, 0x70, 0x8a, 0xbf, 0x27, 0x49, 0xb0, 0x99, - 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6, - 0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, - 0xc6, 0xa4, 0x92, 0xd1, 0xce, 0x6c, 0x72, 0xfb, - 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca, - 0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, - 0xb1, 0xc5, 0x15, 0xf3 - }; - - const uint8 expected_public_key_info[] = { - 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, - 0x89, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, - 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, - 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, - 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, - 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, - 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, - 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, - 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, - 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, - 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, - 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, - 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, - 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, - 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, - 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, - 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, - 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, - 0x00, 0x01 - }; - - std::vector<uint8> input; - input.resize(sizeof(private_key_info)); - memcpy(&input.front(), private_key_info, sizeof(private_key_info)); - - scoped_ptr<base::RSAPrivateKey> key( - base::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); - ASSERT_TRUE(key.get()); - - std::vector<uint8> output; - ASSERT_TRUE(key->ExportPublicKey(&output)); - - ASSERT_TRUE( - memcmp(expected_public_key_info, &output.front(), output.size()) == 0); -} - -// These two test keys each contain an integer that has 0x00 for its most -// significant byte. When encoded as ASN.1, this byte is dropped and there are -// two interesting sub-cases. When the sign bit of the integer is set, an extra -// null byte is added back to force the encoded value to be positive. When the -// sign bit is not set, the encoded integer is just left shorter than usual. -// See also: http://code.google.com/p/chromium/issues/detail?id=14877. -// -// Before we were handling this correctly, we would see one of two failures: -// * RSAPrivateKey::CreateFromPrivateKeyInfo would return null because the -// underlying windows API failed to import the key. -// * The import would succeed, but incorrectly interpret the data. On export, -// the key would contain different values. -// -// This test case verifies these two failures modes don't occur. -TEST(RSAPrivateKeyUnitTest, ShortIntegers) { - const uint8 short_integer_with_high_bit[] = { - 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0x92, 0x59, 0x32, - 0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67, - 0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, - 0xda, 0xe1, 0xa3, 0x1e, 0x40, 0x01, 0x14, 0x5c, - 0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4, - 0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, - 0xf4, 0x53, 0x9f, 0xb8, 0xe0, 0x83, 0x93, 0xd1, - 0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f, - 0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, - 0x1f, 0xc1, 0x20, 0xb0, 0x70, 0xb2, 0x3b, 0xea, - 0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39, - 0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, - 0x12, 0xa4, 0x42, 0x26, 0x6c, 0x6e, 0x79, 0x70, - 0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81, - 0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, - 0x04, 0x58, 0xf5, 0x6b, 0xc9, 0xf1, 0xb5, 0x65, - 0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, - 0xb6, 0x59, 0x1d, 0xdc, 0x36, 0xb6, 0x60, 0x36, - 0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16, - 0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, - 0x68, 0x8f, 0xc5, 0xf8, 0xe2, 0x5d, 0xb3, 0x19, - 0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a, - 0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, - 0x30, 0x98, 0xb1, 0xf7, 0xbd, 0x14, 0x9a, 0x57, - 0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef, - 0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, - 0x54, 0x17, 0x25, 0x5b, 0x37, 0xe3, 0x35, 0x63, - 0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43, - 0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, - 0xda, 0xd7, 0x6f, 0xd2, 0x18, 0xbd, 0x39, 0xf1, - 0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e, - 0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, - 0xc1, 0x91, 0xec, 0xb8, 0x01, 0x02, 0x41, 0x00, - 0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f, - 0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, - 0x96, 0x8d, 0x22, 0x7b, 0x78, 0x73, 0xea, 0xbb, - 0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50, - 0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, - 0xa8, 0xca, 0x54, 0x41, 0xe8, 0xce, 0xbe, 0x7d, - 0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69, - 0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, - 0x02, 0x41, 0x00, 0xbd, 0x1e, 0xfe, 0x51, 0x99, - 0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c, - 0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, - 0x4c, 0xae, 0xa6, 0x41, 0x1c, 0xf0, 0x10, 0x37, - 0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d, - 0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, - 0x05, 0x98, 0x6b, 0x3d, 0x55, 0xb7, 0x6f, 0x7c, - 0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31, - 0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, - 0xa5, 0x9e, 0x12, 0xa7, 0x68, 0xa0, 0x7e, 0xdf, - 0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f, - 0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, - 0x82, 0xfe, 0x7e, 0x33, 0xb1, 0x78, 0x7f, 0x70, - 0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48, - 0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, - 0x86, 0xe5, 0xc9, 0x15, 0x88, 0x14, 0x53, 0xd8, - 0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41, - 0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, - 0xd5, 0xce, 0x8f, 0xfe, 0xbb, 0xc8, 0x5c, 0x30, - 0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89, - 0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, - 0xfd, 0x03, 0xd2, 0xdd, 0xe4, 0xf0, 0xb4, 0x20, - 0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde, - 0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, - 0xcf, 0xec, 0x8a, 0x59, 0x4a, 0x73, 0xca, 0xc5, - 0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4, - 0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, - 0xdb, 0xe5, 0x52, 0x38, 0xf9, 0x59, 0x91, 0x2d, - 0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42, - 0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, - 0x71, 0x10, 0x3a, 0xbd, 0x92, 0x8f, 0x9b, 0xa2, - 0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c, - 0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, - 0x45, 0x84, 0xb0 - }; - - const uint8 short_integer_without_high_bit[] = { - 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x9e, 0x8d, - 0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03, - 0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, - 0x85, 0x27, 0x81, 0x52, 0xf2, 0x1b, 0x3e, 0x5b, - 0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5, - 0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, - 0x92, 0x7e, 0x34, 0xcf, 0x37, 0x82, 0x48, 0x2d, - 0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a, - 0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, - 0x01, 0x00, 0x1b, 0xfe, 0x06, 0x15, 0xc6, 0xe3, - 0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb, - 0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, - 0x53, 0x78, 0x06, 0x03, 0x0d, 0x59, 0xf5, 0x20, - 0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52, - 0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, - 0x02, 0x2d, 0x49, 0xd5, 0x15, 0x5b, 0xf1, 0xd9, - 0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, - 0x95, 0x17, 0x34, 0x88, 0xf6, 0x91, 0xc7, 0x3f, - 0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84, - 0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, - 0xc5, 0x21, 0x61, 0x10, 0xa8, 0x69, 0x09, 0x1e, - 0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b, - 0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, - 0x84, 0x3e, 0xb9, 0xe5, 0xe6, 0x31, 0x0a, 0x01, - 0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6, - 0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, - 0x7b, 0xd3, 0x97, 0x5a, 0x44, 0x3a, 0xee, 0xff, - 0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a, - 0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, - 0xb3, 0xa8, 0xb2, 0xc7, 0x73, 0x25, 0x0f, 0x58, - 0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe, - 0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, - 0xe0, 0x28, 0x15, 0x02, 0x41, 0x00, 0xeb, 0x15, - 0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22, - 0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, - 0xad, 0xf4, 0x57, 0x68, 0x90, 0xb7, 0x9f, 0xe2, - 0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b, - 0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, - 0x1d, 0xb8, 0x5c, 0x96, 0xeb, 0x04, 0x08, 0xe1, - 0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1, - 0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, - 0x00, 0xd5, 0x06, 0x45, 0xd7, 0x55, 0x63, 0x1a, - 0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39, - 0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, - 0xe2, 0x5b, 0xc6, 0xd2, 0x55, 0xdd, 0xab, 0x55, - 0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73, - 0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, - 0x1d, 0xce, 0x18, 0x7f, 0xb0, 0xc8, 0x47, 0x77, - 0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94, - 0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, - 0x17, 0x44, 0x75, 0x0a, 0xf1, 0x10, 0xee, 0x1b, - 0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15, - 0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, - 0xf7, 0x27, 0xe7, 0xe8, 0x2c, 0x47, 0xf1, 0x0f, - 0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19, - 0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, - 0x0b, 0x60, 0x7f, 0x94, 0x2a, 0x80, 0x8d, 0x22, - 0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2, - 0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, - 0x05, 0xc5, 0x3c, 0x9d, 0xcf, 0x8a, 0x60, 0xc7, - 0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3, - 0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, - 0x4a, 0xd2, 0x6a, 0xbc, 0x8b, 0x62, 0x22, 0x3c, - 0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e, - 0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, - 0xb7, 0x3e, 0x91, 0x9c, 0x09, 0xf6, 0xd7, 0x02, - 0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8, - 0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, - 0x91, 0x58, 0xff, 0xf9, 0x19, 0xac, 0x3a, 0x73, - 0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9, - 0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, - 0x43, 0x9b, 0x39, 0xc8, 0x04, 0x4d, 0x2b, 0x01, - 0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43, - 0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, - 0xea, 0xbe - }; - - std::vector<uint8> input1; - std::vector<uint8> input2; - - input1.resize(sizeof(short_integer_with_high_bit)); - input2.resize(sizeof(short_integer_without_high_bit)); - - memcpy(&input1.front(), short_integer_with_high_bit, - sizeof(short_integer_with_high_bit)); - memcpy(&input2.front(), short_integer_without_high_bit, - sizeof(short_integer_without_high_bit)); - - scoped_ptr<base::RSAPrivateKey> keypair1( - base::RSAPrivateKey::CreateFromPrivateKeyInfo(input1)); - scoped_ptr<base::RSAPrivateKey> keypair2( - base::RSAPrivateKey::CreateFromPrivateKeyInfo(input2)); - ASSERT_TRUE(keypair1.get()); - ASSERT_TRUE(keypair2.get()); - - std::vector<uint8> output1; - std::vector<uint8> output2; - ASSERT_TRUE(keypair1->ExportPrivateKey(&output1)); - ASSERT_TRUE(keypair2->ExportPrivateKey(&output2)); - - ASSERT_EQ(input1.size(), output1.size()); - ASSERT_EQ(input2.size(), output2.size()); - ASSERT_TRUE(0 == memcmp(&output1.front(), &input1.front(), - input1.size())); - ASSERT_TRUE(0 == memcmp(&output2.front(), &input2.front(), - input2.size())); -} diff --git a/base/crypto/rsa_private_key_win.cc b/base/crypto/rsa_private_key_win.cc deleted file mode 100644 index 6c8a34b..0000000 --- a/base/crypto/rsa_private_key_win.cc +++ /dev/null @@ -1,229 +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/crypto/rsa_private_key.h" - -#include <list> - -#include "base/logging.h" -#include "base/scoped_ptr.h" -#include "base/string_util.h" - -namespace { - // Helper for error handling during key import. -#define READ_ASSERT(truth) \ - if (!(truth)) { \ - NOTREACHED(); \ - return false; \ - } -} // namespace - -namespace base { - -// static -RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - if (!result->InitProvider()) - return NULL; - - DWORD flags = CRYPT_EXPORTABLE; - - // The size is encoded as the upper 16 bits of the flags. :: sigh ::. - flags |= (num_bits << 16); - if (!CryptGenKey(result->provider_, CALG_RSA_SIGN, flags, - result->key_.receive())) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { - NOTIMPLEMENTED(); - return NULL; -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( - const std::vector<uint8>& input) { - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - if (!result->InitProvider()) - return NULL; - - PrivateKeyInfoCodec pki(false); // Little-Endian - pki.Import(input); - - int blob_size = sizeof(PUBLICKEYSTRUC) + - sizeof(RSAPUBKEY) + - pki.modulus()->size() + - pki.prime1()->size() + - pki.prime2()->size() + - pki.exponent1()->size() + - pki.exponent2()->size() + - pki.coefficient()->size() + - pki.private_exponent()->size(); - scoped_array<BYTE> blob(new BYTE[blob_size]); - - uint8* dest = blob.get(); - PUBLICKEYSTRUC* public_key_struc = reinterpret_cast<PUBLICKEYSTRUC*>(dest); - public_key_struc->bType = PRIVATEKEYBLOB; - public_key_struc->bVersion = 0x02; - public_key_struc->reserved = 0; - public_key_struc->aiKeyAlg = CALG_RSA_SIGN; - dest += sizeof(PUBLICKEYSTRUC); - - RSAPUBKEY* rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(dest); - rsa_pub_key->magic = 0x32415352; - rsa_pub_key->bitlen = pki.modulus()->size() * 8; - int public_exponent_int = 0; - for (size_t i = pki.public_exponent()->size(); i > 0; --i) { - public_exponent_int <<= 8; - public_exponent_int |= (*pki.public_exponent())[i - 1]; - } - rsa_pub_key->pubexp = public_exponent_int; - dest += sizeof(RSAPUBKEY); - - memcpy(dest, &pki.modulus()->front(), pki.modulus()->size()); - dest += pki.modulus()->size(); - memcpy(dest, &pki.prime1()->front(), pki.prime1()->size()); - dest += pki.prime1()->size(); - memcpy(dest, &pki.prime2()->front(), pki.prime2()->size()); - dest += pki.prime2()->size(); - memcpy(dest, &pki.exponent1()->front(), pki.exponent1()->size()); - dest += pki.exponent1()->size(); - memcpy(dest, &pki.exponent2()->front(), pki.exponent2()->size()); - dest += pki.exponent2()->size(); - memcpy(dest, &pki.coefficient()->front(), pki.coefficient()->size()); - dest += pki.coefficient()->size(); - memcpy(dest, &pki.private_exponent()->front(), - pki.private_exponent()->size()); - dest += pki.private_exponent()->size(); - - READ_ASSERT(dest == blob.get() + blob_size); - if (!CryptImportKey(result->provider_, - reinterpret_cast<uint8*>(public_key_struc), blob_size, 0, - CRYPT_EXPORTABLE, result->key_.receive())) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( - const std::vector<uint8>& input) { - NOTIMPLEMENTED(); - return NULL; -} - -// static -RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( - const std::vector<uint8>& input) { - NOTIMPLEMENTED(); - return NULL; -} - -RSAPrivateKey::RSAPrivateKey() : provider_(NULL), key_(NULL) {} - -RSAPrivateKey::~RSAPrivateKey() {} - -bool RSAPrivateKey::InitProvider() { - return FALSE != CryptAcquireContext(provider_.receive(), NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); -} - -bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { - // Export the key - DWORD blob_length = 0; - if (!CryptExportKey(key_, 0, PRIVATEKEYBLOB, 0, NULL, &blob_length)) { - NOTREACHED(); - return false; - } - - scoped_array<uint8> blob(new uint8[blob_length]); - if (!CryptExportKey(key_, 0, PRIVATEKEYBLOB, 0, blob.get(), &blob_length)) { - NOTREACHED(); - return false; - } - - uint8* pos = blob.get(); - PUBLICKEYSTRUC *publickey_struct = reinterpret_cast<PUBLICKEYSTRUC*>(pos); - pos += sizeof(PUBLICKEYSTRUC); - - RSAPUBKEY *rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(pos); - pos += sizeof(RSAPUBKEY); - - int mod_size = rsa_pub_key->bitlen / 8; - int primes_size = rsa_pub_key->bitlen / 16; - - PrivateKeyInfoCodec pki(false); // Little-Endian - - pki.modulus()->assign(pos, pos + mod_size); - pos += mod_size; - - pki.prime1()->assign(pos, pos + primes_size); - pos += primes_size; - pki.prime2()->assign(pos, pos + primes_size); - pos += primes_size; - - pki.exponent1()->assign(pos, pos + primes_size); - pos += primes_size; - pki.exponent2()->assign(pos, pos + primes_size); - pos += primes_size; - - pki.coefficient()->assign(pos, pos + primes_size); - pos += primes_size; - - pki.private_exponent()->assign(pos, pos + mod_size); - pos += mod_size; - - pki.public_exponent()->assign(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp), - reinterpret_cast<uint8*>(&rsa_pub_key->pubexp) + 4); - - CHECK_EQ(pos - blob_length, reinterpret_cast<BYTE*>(publickey_struct)); - - return pki.Export(output); -} - -bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { - DWORD key_info_len; - if (!CryptExportPublicKeyInfo( - provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - NULL, &key_info_len)) { - NOTREACHED(); - return false; - } - - scoped_array<uint8> key_info(new uint8[key_info_len]); - if (!CryptExportPublicKeyInfo( - provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), &key_info_len)) { - NOTREACHED(); - return false; - } - - DWORD encoded_length; - if (!CryptEncodeObject( - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, - reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), NULL, - &encoded_length)) { - NOTREACHED(); - return false; - } - - scoped_array<BYTE> encoded(new BYTE[encoded_length]); - if (!CryptEncodeObject( - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, - reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), encoded.get(), - &encoded_length)) { - NOTREACHED(); - return false; - } - - for (size_t i = 0; i < encoded_length; ++i) - output->push_back(encoded[i]); - - return true; -} - -} // namespace base diff --git a/base/crypto/scoped_capi_types.h b/base/crypto/scoped_capi_types.h deleted file mode 100644 index d6582a7..0000000 --- a/base/crypto/scoped_capi_types.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CRYPTO_SCOPED_CAPI_TYPES_H_ -#define BASE_CRYPTO_SCOPED_CAPI_TYPES_H_ -#pragma once - -#include <windows.h> -#include <wincrypt.h> - -#include <algorithm> - -#include "base/logging.h" - -namespace base { - -// Simple destructor for the Free family of CryptoAPI functions, such as -// CryptDestroyHash, which take only a single argument to release. -template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle)> -struct CAPIDestroyer { - void operator()(CAPIHandle handle) const { - if (handle) { - BOOL ok = Destroyer(handle); - DCHECK(ok); - } - } -}; - -// Destructor for the Close/Release family of CryptoAPI functions, which take -// a second DWORD parameter indicating flags to use when closing or releasing. -// This includes functions like CertCloseStore or CryptReleaseContext. -template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle, DWORD), - DWORD flags> -struct CAPIDestroyerWithFlags { - void operator()(CAPIHandle handle) const { - if (handle) { - BOOL ok = Destroyer(handle, flags); - DCHECK(ok); - } - } -}; - -// scoped_ptr-like class for the CryptoAPI cryptography and certificate -// handles. Because these handles are defined as integer types, and not -// pointers, the existing scoped classes, such as scoped_ptr_malloc, are -// insufficient. The semantics are the same as scoped_ptr. -template <class CAPIHandle, typename FreeProc> -class ScopedCAPIHandle { - public: - explicit ScopedCAPIHandle(CAPIHandle handle = NULL) : handle_(handle) {} - - ~ScopedCAPIHandle() { - free_(handle_); - } - - void reset(CAPIHandle handle = NULL) { - if (handle_ != handle) { - free_(handle_); - handle_ = handle; - } - } - - operator CAPIHandle() const { return handle_; } - CAPIHandle get() const { return handle_; } - - CAPIHandle* receive() { - CHECK(handle_ == NULL); - return &handle_; - } - - bool operator==(CAPIHandle handle) const { - return handle_ == handle; - } - - bool operator!=(CAPIHandle handle) const { - return handle_ != handle; - } - - void swap(ScopedCAPIHandle& b) { - CAPIHandle tmp = b.handle_; - b.handle_ = handle_; - handle_ = tmp; - } - - CAPIHandle release() { - CAPIHandle tmp = handle_; - handle_ = NULL; - return tmp; - } - - private: - CAPIHandle handle_; - static const FreeProc free_; - - DISALLOW_COPY_AND_ASSIGN(ScopedCAPIHandle); -}; - -template<class CH, typename FP> -const FP ScopedCAPIHandle<CH, FP>::free_ = FP(); - -template<class CH, typename FP> inline -bool operator==(CH h, const ScopedCAPIHandle<CH, FP>& b) { - return h == b.get(); -} - -template<class CH, typename FP> inline -bool operator!=(CH h, const ScopedCAPIHandle<CH, FP>& b) { - return h != b.get(); -} - -typedef ScopedCAPIHandle< - HCRYPTPROV, - CAPIDestroyerWithFlags<HCRYPTPROV, - CryptReleaseContext, 0> > ScopedHCRYPTPROV; - -typedef ScopedCAPIHandle< - HCRYPTKEY, CAPIDestroyer<HCRYPTKEY, CryptDestroyKey> > ScopedHCRYPTKEY; - -typedef ScopedCAPIHandle< - HCRYPTHASH, CAPIDestroyer<HCRYPTHASH, CryptDestroyHash> > ScopedHCRYPTHASH; - -} // namespace base - -#endif // BASE_CRYPTO_SCOPED_CAPI_TYPES_H_ diff --git a/base/crypto/scoped_nss_types.h b/base/crypto/scoped_nss_types.h deleted file mode 100644 index 664251f..0000000 --- a/base/crypto/scoped_nss_types.h +++ /dev/null @@ -1,52 +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_SCOPED_NSS_TYPES_H_ -#define BASE_SCOPED_NSS_TYPES_H_ -#pragma once - -#include <nss.h> -#include <pk11pub.h> - -#include "base/scoped_ptr.h" - -namespace base { - -template <typename Type, void (*Destroyer)(Type*)> -struct NSSDestroyer { - void operator()(Type* ptr) const { - if (ptr) - Destroyer(ptr); - } -}; - -template <typename Type, void (*Destroyer)(Type*, PRBool), PRBool freeit> -struct NSSDestroyer1 { - void operator()(Type* ptr) const { - if (ptr) - Destroyer(ptr, freeit); - } -}; - -// Define some convenient scopers around NSS pointers. -typedef scoped_ptr_malloc< - PK11Context, NSSDestroyer1<PK11Context, - PK11_DestroyContext, - PR_TRUE> > ScopedPK11Context; -typedef scoped_ptr_malloc< - PK11SlotInfo, NSSDestroyer<PK11SlotInfo, PK11_FreeSlot> > ScopedPK11Slot; -typedef scoped_ptr_malloc< - PK11SymKey, NSSDestroyer<PK11SymKey, PK11_FreeSymKey> > ScopedPK11SymKey; -typedef scoped_ptr_malloc< - SECAlgorithmID, NSSDestroyer1<SECAlgorithmID, - SECOID_DestroyAlgorithmID, - PR_TRUE> > ScopedSECAlgorithmID; -typedef scoped_ptr_malloc< - SECItem, NSSDestroyer1<SECItem, - SECITEM_FreeItem, - PR_TRUE> > ScopedSECItem; - -} // namespace base - -#endif // BASE_SCOPED_NSS_TYPES_H_ diff --git a/base/crypto/secure_hash.h b/base/crypto/secure_hash.h deleted file mode 100644 index 3759218..0000000 --- a/base/crypto/secure_hash.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CRYPTO_SECURE_HASH_H_ -#define BASE_CRYPTO_SECURE_HASH_H_ -#pragma once - -#include "base/basictypes.h" - -namespace base { - -// A wrapper to calculate secure hashes incrementally, allowing to -// be used when the full input is not known in advance. -class SecureHash { - public: - enum Algorithm { - SHA256, - }; - virtual ~SecureHash() {} - - static SecureHash* Create(Algorithm type); - - virtual void Update(const void* input, size_t len) = 0; - virtual void Finish(void* output, size_t len) = 0; - - protected: - SecureHash() {} - - private: - DISALLOW_COPY_AND_ASSIGN(SecureHash); -}; - -} // namespace base - -#endif // BASE_CRYPTO_SECURE_HASH_H_ diff --git a/base/crypto/secure_hash_default.cc b/base/crypto/secure_hash_default.cc deleted file mode 100644 index 436867e..0000000 --- a/base/crypto/secure_hash_default.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/crypto/secure_hash.h" - -#include "base/logging.h" -#include "base/third_party/nss/blapi.h" -#include "base/third_party/nss/sha256.h" - -namespace base { - -namespace { - -class SecureHashSHA256NSS : public SecureHash { - public: - SecureHashSHA256NSS() { - SHA256_Begin(&ctx_); - } - - virtual ~SecureHashSHA256NSS() { - } - - virtual void Update(const void* input, size_t len) { - SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len); - } - - virtual void Finish(void* output, size_t len) { - SHA256_End(&ctx_, static_cast<unsigned char*>(output), NULL, - static_cast<unsigned int>(len)); - } - - private: - SHA256Context ctx_; -}; - -} // namespace - -SecureHash* SecureHash::Create(Algorithm algorithm) { - switch (algorithm) { - case SHA256: - return new SecureHashSHA256NSS(); - default: - NOTIMPLEMENTED(); - return NULL; - } -} - -} // namespace base diff --git a/base/crypto/secure_hash_openssl.cc b/base/crypto/secure_hash_openssl.cc deleted file mode 100644 index 8087279..0000000 --- a/base/crypto/secure_hash_openssl.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/crypto/secure_hash.h" - -#include <openssl/ssl.h> - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/openssl_util.h" - -namespace base { - -namespace { - -class SecureHashSHA256OpenSSL : public SecureHash { - public: - SecureHashSHA256OpenSSL() { - SHA256_Init(&ctx_); - } - - virtual ~SecureHashSHA256OpenSSL() { - OPENSSL_cleanse(&ctx_, sizeof(ctx_)); - } - - virtual void Update(const void* input, size_t len) { - SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len); - } - - virtual void Finish(void* output, size_t len) { - ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result( - static_cast<unsigned char*>(output), len); - SHA256_Final(result.safe_buffer(), &ctx_); - } - - private: - SHA256_CTX ctx_; -}; - -} // namespace - -SecureHash* SecureHash::Create(Algorithm algorithm) { - switch (algorithm) { - case SHA256: - return new SecureHashSHA256OpenSSL(); - default: - NOTIMPLEMENTED(); - return NULL; - } -} - -} // namespace base diff --git a/base/crypto/secure_hash_unittest.cc b/base/crypto/secure_hash_unittest.cc deleted file mode 100644 index 2dac928..0000000 --- a/base/crypto/secure_hash_unittest.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/crypto/secure_hash.h" - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" -#include "base/sha2.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(SecureHashTest, TestUpdate) { - // Example B.3 from FIPS 180-2: long message. - std::string input3(500000, 'a'); // 'a' repeated half a million times - int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c, - 0x99, 0x14, 0xfb, 0x92, - 0x81, 0xa1, 0xc7, 0xe2, - 0x84, 0xd7, 0x3e, 0x67, - 0xf1, 0x80, 0x9a, 0x48, - 0xa4, 0x97, 0x20, 0x0e, - 0x04, 0x6d, 0x39, 0xcc, - 0xc7, 0x11, 0x2c, 0xd0 }; - - uint8 output3[base::SHA256_LENGTH]; - - scoped_ptr<base::SecureHash> ctx(base::SecureHash::Create( - base::SecureHash::SHA256)); - ctx->Update(input3.data(), input3.size()); - ctx->Update(input3.data(), input3.size()); - - ctx->Finish(output3, sizeof(output3)); - for (size_t i = 0; i < base::SHA256_LENGTH; i++) - EXPECT_EQ(expected3[i], static_cast<int>(output3[i])); -} diff --git a/base/crypto/signature_creator.h b/base/crypto/signature_creator.h deleted file mode 100644 index 3e3afd2..0000000 --- a/base/crypto/signature_creator.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CRYPTO_SIGNATURE_CREATOR_H_ -#define BASE_CRYPTO_SIGNATURE_CREATOR_H_ -#pragma once - -#include "build/build_config.h" - -#if defined(USE_OPENSSL) -// Forward declaration for openssl/*.h -typedef struct env_md_ctx_st EVP_MD_CTX; -#elif defined(USE_NSS) -// Forward declaration. -struct SGNContextStr; -#elif defined(OS_MACOSX) -#include <Security/cssm.h> -#endif - -#include <vector> - -#include "base/basictypes.h" -#include "base/crypto/rsa_private_key.h" - -#if defined(OS_WIN) -#include "base/crypto/scoped_capi_types.h" -#endif - -namespace base { - -// Signs data using a bare private key (as opposed to a full certificate). -// Currently can only sign data using SHA-1 with RSA encryption. -class SignatureCreator { - public: - ~SignatureCreator(); - - // Create an instance. The caller must ensure that the provided PrivateKey - // instance outlives the created SignatureCreator. - static SignatureCreator* Create(RSAPrivateKey* key); - - // Update the signature with more data. - bool Update(const uint8* data_part, int data_part_len); - - // Finalize the signature. - bool Final(std::vector<uint8>* signature); - - private: - // Private constructor. Use the Create() method instead. - SignatureCreator(); - - RSAPrivateKey* key_; - -#if defined(USE_OPENSSL) - EVP_MD_CTX* sign_context_; -#elif defined(USE_NSS) - SGNContextStr* sign_context_; -#elif defined(OS_MACOSX) - CSSM_CC_HANDLE sig_handle_; -#elif defined(OS_WIN) - ScopedHCRYPTHASH hash_object_; -#endif - - DISALLOW_COPY_AND_ASSIGN(SignatureCreator); -}; - -} // namespace base - -#endif // BASE_CRYPTO_SIGNATURE_CREATOR_H_ diff --git a/base/crypto/signature_creator_mac.cc b/base/crypto/signature_creator_mac.cc deleted file mode 100644 index 1001c64..0000000 --- a/base/crypto/signature_creator_mac.cc +++ /dev/null @@ -1,74 +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/crypto/signature_creator.h" - -#include <stdlib.h> - -#include "base/crypto/cssm_init.h" -#include "base/logging.h" -#include "base/scoped_ptr.h" - -namespace base { - -// static -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { - scoped_ptr<SignatureCreator> result(new SignatureCreator); - result->key_ = key; - - CSSM_RETURN crtn; - crtn = CSSM_CSP_CreateSignatureContext(GetSharedCSPHandle(), - CSSM_ALGID_SHA1WithRSA, - NULL, - key->key(), - &result->sig_handle_); - if (crtn) { - NOTREACHED(); - return NULL; - } - - crtn = CSSM_SignDataInit(result->sig_handle_); - if (crtn) { - NOTREACHED(); - return NULL; - } - - return result.release(); -} - -SignatureCreator::SignatureCreator() : sig_handle_(0) { - EnsureCSSMInit(); -} - -SignatureCreator::~SignatureCreator() { - CSSM_RETURN crtn; - if (sig_handle_) { - crtn = CSSM_DeleteContext(sig_handle_); - DCHECK(crtn == CSSM_OK); - } -} - -bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { - CSSM_DATA data; - data.Data = const_cast<uint8*>(data_part); - data.Length = data_part_len; - CSSM_RETURN crtn = CSSM_SignDataUpdate(sig_handle_, &data, 1); - DCHECK(crtn == CSSM_OK); - return true; -} - -bool SignatureCreator::Final(std::vector<uint8>* signature) { - ScopedCSSMData sig; - CSSM_RETURN crtn = CSSM_SignDataFinal(sig_handle_, sig); - - if (crtn) { - NOTREACHED(); - return false; - } - - signature->assign(sig->Data, sig->Data + sig->Length); - return true; -} - -} // namespace base diff --git a/base/crypto/signature_creator_nss.cc b/base/crypto/signature_creator_nss.cc deleted file mode 100644 index 4cc2c10..0000000 --- a/base/crypto/signature_creator_nss.cc +++ /dev/null @@ -1,76 +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/crypto/signature_creator.h" - -#include <cryptohi.h> -#include <keyhi.h> -#include <stdlib.h> - -#include "base/logging.h" -#include "base/nss_util.h" -#include "base/scoped_ptr.h" - -namespace base { - -SignatureCreator::~SignatureCreator() { - if (sign_context_) { - SGN_DestroyContext(sign_context_, PR_TRUE); - sign_context_ = NULL; - } -} - -// static -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { - scoped_ptr<SignatureCreator> result(new SignatureCreator); - result->key_ = key; - - result->sign_context_ = SGN_NewContext(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, - key->key()); - if (!result->sign_context_) { - NOTREACHED(); - return NULL; - } - - SECStatus rv = SGN_Begin(result->sign_context_); - if (rv != SECSuccess) { - NOTREACHED(); - return NULL; - } - - return result.release(); -} - -bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { - // TODO(wtc): Remove this const_cast when we require NSS 3.12.5. - // See NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=518255 - SECStatus rv = SGN_Update(sign_context_, - const_cast<unsigned char*>(data_part), - data_part_len); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - - return true; -} - -bool SignatureCreator::Final(std::vector<uint8>* signature) { - SECItem signature_item; - SECStatus rv = SGN_End(sign_context_, &signature_item); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - signature->assign(signature_item.data, - signature_item.data + signature_item.len); - SECITEM_FreeItem(&signature_item, PR_FALSE); - return true; -} - -SignatureCreator::SignatureCreator() : sign_context_(NULL) { - EnsureNSSInit(); -} - -} // namespace base diff --git a/base/crypto/signature_creator_openssl.cc b/base/crypto/signature_creator_openssl.cc deleted file mode 100644 index 5bdb783..0000000 --- a/base/crypto/signature_creator_openssl.cc +++ /dev/null @@ -1,54 +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/crypto/signature_creator.h" - -#include <openssl/evp.h> - -#include "base/logging.h" -#include "base/openssl_util.h" -#include "base/scoped_ptr.h" -#include "base/stl_util-inl.h" - -namespace base { - -// static -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - scoped_ptr<SignatureCreator> result(new SignatureCreator); - result->key_ = key; - if (!EVP_SignInit_ex(result->sign_context_, EVP_sha1(), NULL)) - return NULL; - return result.release(); -} - -SignatureCreator::SignatureCreator() - : sign_context_(EVP_MD_CTX_create()) { -} - -SignatureCreator::~SignatureCreator() { - EVP_MD_CTX_destroy(sign_context_); -} - -bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - return EVP_SignUpdate(sign_context_, data_part, data_part_len) == 1; -} - -bool SignatureCreator::Final(std::vector<uint8>* signature) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - EVP_PKEY* key = key_->key(); - signature->resize(EVP_PKEY_size(key)); - - unsigned int len = 0; - int rv = EVP_SignFinal(sign_context_, vector_as_array(signature), &len, key); - if (!rv) { - signature->clear(); - return false; - } - signature->resize(len); - return true; -} - -} // namespace base diff --git a/base/crypto/signature_creator_unittest.cc b/base/crypto/signature_creator_unittest.cc deleted file mode 100644 index 11959cb..0000000 --- a/base/crypto/signature_creator_unittest.cc +++ /dev/null @@ -1,53 +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 <vector> - -#include "base/crypto/signature_creator.h" -#include "base/crypto/signature_verifier.h" -#include "base/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(SignatureCreatorTest, BasicTest) { - // Do a verify round trip. - scoped_ptr<base::RSAPrivateKey> key_original( - base::RSAPrivateKey::Create(1024)); - ASSERT_TRUE(key_original.get()); - - std::vector<uint8> key_info; - key_original->ExportPrivateKey(&key_info); - scoped_ptr<base::RSAPrivateKey> key( - base::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info)); - ASSERT_TRUE(key.get()); - - scoped_ptr<base::SignatureCreator> signer( - base::SignatureCreator::Create(key.get())); - ASSERT_TRUE(signer.get()); - - std::string data("Hello, World!"); - ASSERT_TRUE(signer->Update(reinterpret_cast<const uint8*>(data.c_str()), - data.size())); - - std::vector<uint8> signature; - ASSERT_TRUE(signer->Final(&signature)); - - std::vector<uint8> public_key_info; - ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); - - // This is the algorithm ID for SHA-1 with RSA encryption. - // TODO(aa): Factor this out into some shared location. - const uint8 kSHA1WithRSAAlgorithmID[] = { - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00 - }; - base::SignatureVerifier verifier; - ASSERT_TRUE(verifier.VerifyInit( - kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID), - &signature.front(), signature.size(), - &public_key_info.front(), public_key_info.size())); - - verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()), - data.size()); - ASSERT_TRUE(verifier.VerifyFinal()); -} diff --git a/base/crypto/signature_creator_win.cc b/base/crypto/signature_creator_win.cc deleted file mode 100644 index 45924f0..0000000 --- a/base/crypto/signature_creator_win.cc +++ /dev/null @@ -1,60 +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/crypto/signature_creator.h" - -#include "base/logging.h" -#include "base/scoped_ptr.h" - -namespace base { - -// static -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { - scoped_ptr<SignatureCreator> result(new SignatureCreator); - result->key_ = key; - - if (!CryptCreateHash(key->provider(), CALG_SHA1, 0, 0, - result->hash_object_.receive())) { - NOTREACHED(); - return NULL; - } - - return result.release(); -} - -SignatureCreator::SignatureCreator() : hash_object_(0) {} - -SignatureCreator::~SignatureCreator() {} - -bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { - if (!CryptHashData(hash_object_, data_part, data_part_len, 0)) { - NOTREACHED(); - return false; - } - - return true; -} - -bool SignatureCreator::Final(std::vector<uint8>* signature) { - DWORD signature_length = 0; - if (!CryptSignHash(hash_object_, AT_SIGNATURE, NULL, 0, NULL, - &signature_length)) { - return false; - } - - std::vector<uint8> temp; - temp.resize(signature_length); - if (!CryptSignHash(hash_object_, AT_SIGNATURE, NULL, 0, &temp.front(), - &signature_length)) { - return false; - } - - temp.resize(signature_length); - for (size_t i = temp.size(); i > 0; --i) - signature->push_back(temp[i - 1]); - - return true; -} - -} // namespace base diff --git a/base/crypto/signature_verifier.h b/base/crypto/signature_verifier.h deleted file mode 100644 index e2b61af..0000000 --- a/base/crypto/signature_verifier.h +++ /dev/null @@ -1,108 +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_CRYPTO_SIGNATURE_VERIFIER_H_ -#define BASE_CRYPTO_SIGNATURE_VERIFIER_H_ -#pragma once - -#include "build/build_config.h" - -#if defined(USE_NSS) -#include <cryptoht.h> -#elif defined(OS_MACOSX) -#include <Security/cssm.h> -#endif - -#include <vector> - -#include "base/basictypes.h" - -#if defined(OS_WIN) -#include "base/crypto/scoped_capi_types.h" -#endif - -namespace base { - -// The SignatureVerifier class verifies a signature using a bare public key -// (as opposed to a certificate). -class SignatureVerifier { - public: - SignatureVerifier(); - ~SignatureVerifier(); - - // Streaming interface: - - // Initiates a signature verification operation. This should be followed - // by one or more VerifyUpdate calls and a VerifyFinal call. - // - // The signature algorithm is specified as a DER encoded ASN.1 - // AlgorithmIdentifier structure: - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - // - // The signature is encoded according to the signature algorithm, but it - // must not be further encoded in an ASN.1 BIT STRING. - // Note: An RSA signatures is actually a big integer. It must be in the - // big-endian byte order. - // - // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo - // structure, which contains not only the public key but also its type - // (algorithm): - // SubjectPublicKeyInfo ::= SEQUENCE { - // algorithm AlgorithmIdentifier, - // subjectPublicKey BIT STRING } - bool VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len); - - // Feeds a piece of the data to the signature verifier. - void VerifyUpdate(const uint8* data_part, int data_part_len); - - // Concludes a signature verification operation. Returns true if the - // signature is valid. Returns false if the signature is invalid or an - // error occurred. - bool VerifyFinal(); - - // Note: we can provide a one-shot interface if there is interest: - // bool Verify(const uint8* data, - // int data_len, - // const uint8* signature_algorithm, - // int signature_algorithm_len, - // const uint8* signature, - // int signature_len, - // const uint8* public_key_info, - // int public_key_info_len); - - private: - void Reset(); - - std::vector<uint8> signature_; - -#if defined(USE_OPENSSL) - struct VerifyContext; - VerifyContext* verify_context_; -#elif defined(USE_NSS) - VFYContext* vfy_context_; -#elif defined(OS_MACOSX) - std::vector<uint8> public_key_info_; - - CSSM_CC_HANDLE sig_handle_; - - CSSM_KEY public_key_; -#elif defined(OS_WIN) - ScopedHCRYPTPROV provider_; - - ScopedHCRYPTHASH hash_object_; - - ScopedHCRYPTKEY public_key_; -#endif -}; - -} // namespace base - -#endif // BASE_CRYPTO_SIGNATURE_VERIFIER_H_ diff --git a/base/crypto/signature_verifier_mac.cc b/base/crypto/signature_verifier_mac.cc deleted file mode 100644 index c8bfa8b..0000000 --- a/base/crypto/signature_verifier_mac.cc +++ /dev/null @@ -1,105 +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/crypto/signature_verifier.h" - -#include <stdlib.h> - -#include "base/crypto/cssm_init.h" -#include "base/logging.h" - -namespace base { - -SignatureVerifier::SignatureVerifier() : sig_handle_(0) { - EnsureCSSMInit(); -} - -SignatureVerifier::~SignatureVerifier() { - Reset(); -} - -bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - signature_.assign(signature, signature + signature_len); - public_key_info_.assign(public_key_info, - public_key_info + public_key_info_len); - - CSSM_ALGORITHMS key_alg = CSSM_ALGID_RSA; // TODO(wtc): hardcoded. - - memset(&public_key_, 0, sizeof(public_key_)); - public_key_.KeyData.Data = const_cast<uint8*>(&public_key_info_[0]); - public_key_.KeyData.Length = public_key_info_.size(); - public_key_.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; - public_key_.KeyHeader.BlobType = CSSM_KEYBLOB_RAW; - public_key_.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_X509; - public_key_.KeyHeader.AlgorithmId = key_alg; - public_key_.KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; - public_key_.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; - public_key_.KeyHeader.KeyUsage = CSSM_KEYUSE_VERIFY; - CSSM_KEY_SIZE key_size; - CSSM_RETURN crtn; - crtn = CSSM_QueryKeySizeInBits(GetSharedCSPHandle(), NULL, - &public_key_, &key_size); - if (crtn) { - NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn; - return false; - } - public_key_.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits; - - // TODO(wtc): decode signature_algorithm... - CSSM_ALGORITHMS sig_alg = CSSM_ALGID_SHA1WithRSA; - - crtn = CSSM_CSP_CreateSignatureContext(GetSharedCSPHandle(), sig_alg, NULL, - &public_key_, &sig_handle_); - if (crtn) { - NOTREACHED(); - return false; - } - crtn = CSSM_VerifyDataInit(sig_handle_); - if (crtn) { - NOTREACHED(); - return false; - } - return true; -} - -void SignatureVerifier::VerifyUpdate(const uint8* data_part, - int data_part_len) { - CSSM_DATA data; - data.Data = const_cast<uint8*>(data_part); - data.Length = data_part_len; - CSSM_RETURN crtn = CSSM_VerifyDataUpdate(sig_handle_, &data, 1); - DCHECK(crtn == CSSM_OK); -} - -bool SignatureVerifier::VerifyFinal() { - CSSM_DATA sig; - sig.Data = const_cast<uint8*>(&signature_[0]); - sig.Length = signature_.size(); - CSSM_RETURN crtn = CSSM_VerifyDataFinal(sig_handle_, &sig); - Reset(); - - // crtn is CSSMERR_CSP_VERIFY_FAILED if signature verification fails. - return (crtn == CSSM_OK); -} - -void SignatureVerifier::Reset() { - CSSM_RETURN crtn; - if (sig_handle_) { - crtn = CSSM_DeleteContext(sig_handle_); - DCHECK(crtn == CSSM_OK); - sig_handle_ = 0; - } - signature_.clear(); - - // Can't call CSSM_FreeKey on public_key_ because we constructed - // public_key_ manually. -} - -} // namespace base - diff --git a/base/crypto/signature_verifier_nss.cc b/base/crypto/signature_verifier_nss.cc deleted file mode 100644 index 369f275..0000000 --- a/base/crypto/signature_verifier_nss.cc +++ /dev/null @@ -1,113 +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/crypto/signature_verifier.h" - -#include <cryptohi.h> -#include <keyhi.h> -#include <stdlib.h> - -#include "base/logging.h" -#include "base/nss_util.h" - -namespace base { - -SignatureVerifier::SignatureVerifier() : vfy_context_(NULL) { - EnsureNSSInit(); -} - -SignatureVerifier::~SignatureVerifier() { - Reset(); -} - -bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - signature_.assign(signature, signature + signature_len); - - CERTSubjectPublicKeyInfo* spki = NULL; - SECItem spki_der; - spki_der.type = siBuffer; - spki_der.data = const_cast<uint8*>(public_key_info); - spki_der.len = public_key_info_len; - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); - if (!spki) - return false; - SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); - SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. - if (!public_key) - return false; - - PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - SECKEY_DestroyPublicKey(public_key); - return false; - } - - SECItem sig_alg_der; - sig_alg_der.type = siBuffer; - sig_alg_der.data = const_cast<uint8*>(signature_algorithm); - sig_alg_der.len = signature_algorithm_len; - SECAlgorithmID sig_alg_id; - SECStatus rv; - rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, SECOID_AlgorithmIDTemplate, - &sig_alg_der); - if (rv != SECSuccess) { - SECKEY_DestroyPublicKey(public_key); - PORT_FreeArena(arena, PR_TRUE); - return false; - } - - SECItem sig; - sig.type = siBuffer; - sig.data = const_cast<uint8*>(signature); - sig.len = signature_len; - SECOidTag hash_alg_tag; - vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig, - &sig_alg_id, &hash_alg_tag, - NULL); - SECKEY_DestroyPublicKey(public_key); // Done with public_key. - PORT_FreeArena(arena, PR_TRUE); // Done with sig_alg_id. - if (!vfy_context_) { - // A corrupted RSA signature could be detected without the data, so - // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE - // (-8182). - return false; - } - - rv = VFY_Begin(vfy_context_); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - return true; -} - -void SignatureVerifier::VerifyUpdate(const uint8* data_part, - int data_part_len) { - SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); - DCHECK(rv == SECSuccess); -} - -bool SignatureVerifier::VerifyFinal() { - SECStatus rv = VFY_End(vfy_context_); - Reset(); - - // If signature verification fails, the error code is - // SEC_ERROR_BAD_SIGNATURE (-8182). - return (rv == SECSuccess); -} - -void SignatureVerifier::Reset() { - if (vfy_context_) { - VFY_DestroyContext(vfy_context_, PR_TRUE); - vfy_context_ = NULL; - } - signature_.clear(); -} - -} // namespace base diff --git a/base/crypto/signature_verifier_openssl.cc b/base/crypto/signature_verifier_openssl.cc deleted file mode 100644 index 4850efa..0000000 --- a/base/crypto/signature_verifier_openssl.cc +++ /dev/null @@ -1,94 +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/crypto/signature_verifier.h" - -#include <openssl/evp.h> -#include <openssl/x509.h> - -#include <vector> - -#include "base/logging.h" -#include "base/openssl_util.h" -#include "base/scoped_ptr.h" -#include "base/stl_util-inl.h" - -namespace base { - -struct SignatureVerifier::VerifyContext { - ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> public_key; - ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> ctx; -}; - -SignatureVerifier::SignatureVerifier() - : verify_context_(NULL) { -} - -SignatureVerifier::~SignatureVerifier() { - Reset(); -} - -bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - DCHECK(!verify_context_); - verify_context_ = new VerifyContext; - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free> algorithm( - d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len)); - if (!algorithm.get()) - return false; - - const EVP_MD* digest = EVP_get_digestbyobj(algorithm.get()->algorithm); - DCHECK(digest); - - signature_.assign(signature, signature + signature_len); - - // BIO_new_mem_buf is not const aware, but it does not modify the buffer. - char* data = reinterpret_cast<char*>(const_cast<uint8*>(public_key_info)); - ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, - public_key_info_len)); - if (!bio.get()) - return false; - - verify_context_->public_key.reset(d2i_PUBKEY_bio(bio.get(), NULL)); - if (!verify_context_->public_key.get()) - return false; - - verify_context_->ctx.reset(EVP_MD_CTX_create()); - int rv = EVP_VerifyInit_ex(verify_context_->ctx.get(), digest, NULL); - return rv == 1; -} - -void SignatureVerifier::VerifyUpdate(const uint8* data_part, - int data_part_len) { - DCHECK(verify_context_); - OpenSSLErrStackTracer err_tracer(FROM_HERE); - int rv = EVP_VerifyUpdate(verify_context_->ctx.get(), - data_part, data_part_len); - DCHECK_EQ(rv, 1); -} - -bool SignatureVerifier::VerifyFinal() { - DCHECK(verify_context_); - OpenSSLErrStackTracer err_tracer(FROM_HERE); - int rv = EVP_VerifyFinal(verify_context_->ctx.get(), - vector_as_array(&signature_), signature_.size(), - verify_context_->public_key.get()); - DCHECK_GE(rv, 0); - Reset(); - return rv == 1; -} - -void SignatureVerifier::Reset() { - delete verify_context_; - verify_context_ = NULL; - signature_.clear(); -} - -} // namespace base diff --git a/base/crypto/signature_verifier_unittest.cc b/base/crypto/signature_verifier_unittest.cc deleted file mode 100644 index e28395f..0000000 --- a/base/crypto/signature_verifier_unittest.cc +++ /dev/null @@ -1,268 +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/crypto/signature_verifier.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(SignatureVerifierTest, BasicTest) { - // The input data in this test comes from real certificates. - // - // tbs_certificate ("to-be-signed certificate", the part of a certificate - // that is signed), signature_algorithm, and algorithm come from the - // certificate of bugs.webkit.org. - // - // public_key_info comes from the certificate of the issuer, Go Daddy Secure - // Certification Authority. - // - // The bytes in the array initializers are formatted to expose the DER - // encoding of the ASN.1 structures. - - // The data that is signed is the following ASN.1 structure: - // TBSCertificate ::= SEQUENCE { - // ... -- omitted, not important - // } - const uint8 tbs_certificate[1017] = { - 0x30, 0x82, 0x03, 0xf5, // a SEQUENCE of length 1013 (0x3f5) - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x43, 0xdd, 0x63, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, - 0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, - 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, - 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, - 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, - 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, - 0x38, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, 0x31, 0x38, - 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x33, 0x31, 0x38, 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x30, 0x79, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, - 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, - 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0c, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x46, 0x6f, 0x72, - 0x67, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72, - 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa7, 0x62, 0x79, 0x41, 0xda, 0x28, - 0xf2, 0xc0, 0x4f, 0xe0, 0x25, 0xaa, 0xa1, 0x2e, 0x3b, 0x30, 0x94, 0xb5, - 0xc9, 0x26, 0x3a, 0x1b, 0xe2, 0xd0, 0xcc, 0xa2, 0x95, 0xe2, 0x91, 0xc0, - 0xf0, 0x40, 0x9e, 0x27, 0x6e, 0xbd, 0x6e, 0xde, 0x7c, 0xb6, 0x30, 0x5c, - 0xb8, 0x9b, 0x01, 0x2f, 0x92, 0x04, 0xa1, 0xef, 0x4a, 0xb1, 0x6c, 0xb1, - 0x7e, 0x8e, 0xcd, 0xa6, 0xf4, 0x40, 0x73, 0x1f, 0x2c, 0x96, 0xad, 0xff, - 0x2a, 0x6d, 0x0e, 0xba, 0x52, 0x84, 0x83, 0xb0, 0x39, 0xee, 0xc9, 0x39, - 0xdc, 0x1e, 0x34, 0xd0, 0xd8, 0x5d, 0x7a, 0x09, 0xac, 0xa9, 0xee, 0xca, - 0x65, 0xf6, 0x85, 0x3a, 0x6b, 0xee, 0xe4, 0x5c, 0x5e, 0xf8, 0xda, 0xd1, - 0xce, 0x88, 0x47, 0xcd, 0x06, 0x21, 0xe0, 0xb9, 0x4b, 0xe4, 0x07, 0xcb, - 0x57, 0xdc, 0xca, 0x99, 0x54, 0xf7, 0x0e, 0xd5, 0x17, 0x95, 0x05, 0x2e, - 0xe9, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xce, 0x30, - 0x82, 0x01, 0xca, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, - 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, - 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x57, - 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x50, 0x30, 0x4e, 0x30, 0x4c, 0xa0, - 0x4a, 0xa0, 0x48, 0x86, 0x46, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, - 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, - 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x64, 0x65, 0x64, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, 0x33, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x52, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4b, - 0x30, 0x49, 0x30, 0x47, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, - 0x6d, 0x01, 0x07, 0x17, 0x02, 0x30, 0x38, 0x30, 0x36, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x2a, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x30, 0x7f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x23, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64, - 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x4a, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, - 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72, 0x74, - 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48, - 0xdf, 0x60, 0x32, 0xcc, 0x89, 0x01, 0xb6, 0xdc, 0x2f, 0xe3, 0x73, 0xb5, - 0x9c, 0x16, 0x58, 0x32, 0x68, 0xa9, 0xc3, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, - 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee, 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, - 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x23, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, - 0x1c, 0x30, 0x1a, 0x82, 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, - 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x0a, 0x77, 0x65, 0x62, 0x6b, 0x69, - 0x74, 0x2e, 0x6f, 0x72, 0x67 - }; - - // The signature algorithm is specified as the following ASN.1 structure: - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - // - const uint8 signature_algorithm[15] = { - 0x30, 0x0d, // a SEQUENCE of length 13 (0xd) - 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 - // 1.2.840.113549.1.1.5 - sha1WithRSAEncryption - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, // a NULL of length 0 - }; - - // RSA signature, a big integer in the big-endian byte order. - const uint8 signature[256] = { - 0x1e, 0x6a, 0xe7, 0xe0, 0x4f, 0xe7, 0x4d, 0xd0, 0x69, 0x7c, 0xf8, 0x8f, - 0x99, 0xb4, 0x18, 0x95, 0x36, 0x24, 0x0f, 0x0e, 0xa3, 0xea, 0x34, 0x37, - 0xf4, 0x7d, 0xd5, 0x92, 0x35, 0x53, 0x72, 0x76, 0x3f, 0x69, 0xf0, 0x82, - 0x56, 0xe3, 0x94, 0x7a, 0x1d, 0x1a, 0x81, 0xaf, 0x9f, 0xc7, 0x43, 0x01, - 0x64, 0xd3, 0x7c, 0x0d, 0xc8, 0x11, 0x4e, 0x4a, 0xe6, 0x1a, 0xc3, 0x01, - 0x74, 0xe8, 0x35, 0x87, 0x5c, 0x61, 0xaa, 0x8a, 0x46, 0x06, 0xbe, 0x98, - 0x95, 0x24, 0x9e, 0x01, 0xe3, 0xe6, 0xa0, 0x98, 0xee, 0x36, 0x44, 0x56, - 0x8d, 0x23, 0x9c, 0x65, 0xea, 0x55, 0x6a, 0xdf, 0x66, 0xee, 0x45, 0xe8, - 0xa0, 0xe9, 0x7d, 0x9a, 0xba, 0x94, 0xc5, 0xc8, 0xc4, 0x4b, 0x98, 0xff, - 0x9a, 0x01, 0x31, 0x6d, 0xf9, 0x2b, 0x58, 0xe7, 0xe7, 0x2a, 0xc5, 0x4d, - 0xbb, 0xbb, 0xcd, 0x0d, 0x70, 0xe1, 0xad, 0x03, 0xf5, 0xfe, 0xf4, 0x84, - 0x71, 0x08, 0xd2, 0xbc, 0x04, 0x7b, 0x26, 0x1c, 0xa8, 0x0f, 0x9c, 0xd8, - 0x12, 0x6a, 0x6f, 0x2b, 0x67, 0xa1, 0x03, 0x80, 0x9a, 0x11, 0x0b, 0xe9, - 0xe0, 0xb5, 0xb3, 0xb8, 0x19, 0x4e, 0x0c, 0xa4, 0xd9, 0x2b, 0x3b, 0xc2, - 0xca, 0x20, 0xd3, 0x0c, 0xa4, 0xff, 0x93, 0x13, 0x1f, 0xfc, 0xba, 0x94, - 0x93, 0x8c, 0x64, 0x15, 0x2e, 0x28, 0xa9, 0x55, 0x8c, 0x2c, 0x48, 0xd3, - 0xd3, 0xc1, 0x50, 0x69, 0x19, 0xe8, 0x34, 0xd3, 0xf1, 0x04, 0x9f, 0x0a, - 0x7a, 0x21, 0x87, 0xbf, 0xb9, 0x59, 0x37, 0x2e, 0xf4, 0x71, 0xa5, 0x3e, - 0xbe, 0xcd, 0x70, 0x83, 0x18, 0xf8, 0x8a, 0x72, 0x85, 0x45, 0x1f, 0x08, - 0x01, 0x6f, 0x37, 0xf5, 0x2b, 0x7b, 0xea, 0xb9, 0x8b, 0xa3, 0xcc, 0xfd, - 0x35, 0x52, 0xdd, 0x66, 0xde, 0x4f, 0x30, 0xc5, 0x73, 0x81, 0xb6, 0xe8, - 0x3c, 0xd8, 0x48, 0x8a - }; - - // The public key is specified as the following ASN.1 structure: - // SubjectPublicKeyInfo ::= SEQUENCE { - // algorithm AlgorithmIdentifier, - // subjectPublicKey BIT STRING } - const uint8 public_key_info[294] = { - 0x30, 0x82, 0x01, 0x22, // a SEQUENCE of length 290 (0x122) - // algorithm - 0x30, 0x0d, // a SEQUENCE of length 13 - 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, // a NULL of length 0 - // subjectPublicKey - 0x03, 0x82, 0x01, 0x0f, // a BIT STRING of length 271 (0x10f) - 0x00, // number of unused bits - 0x30, 0x82, 0x01, 0x0a, // a SEQUENCE of length 266 (0x10a) - // modulus - 0x02, 0x82, 0x01, 0x01, // an INTEGER of length 257 (0x101) - 0x00, 0xc4, 0x2d, 0xd5, 0x15, 0x8c, 0x9c, 0x26, 0x4c, 0xec, - 0x32, 0x35, 0xeb, 0x5f, 0xb8, 0x59, 0x01, 0x5a, 0xa6, 0x61, - 0x81, 0x59, 0x3b, 0x70, 0x63, 0xab, 0xe3, 0xdc, 0x3d, 0xc7, - 0x2a, 0xb8, 0xc9, 0x33, 0xd3, 0x79, 0xe4, 0x3a, 0xed, 0x3c, - 0x30, 0x23, 0x84, 0x8e, 0xb3, 0x30, 0x14, 0xb6, 0xb2, 0x87, - 0xc3, 0x3d, 0x95, 0x54, 0x04, 0x9e, 0xdf, 0x99, 0xdd, 0x0b, - 0x25, 0x1e, 0x21, 0xde, 0x65, 0x29, 0x7e, 0x35, 0xa8, 0xa9, - 0x54, 0xeb, 0xf6, 0xf7, 0x32, 0x39, 0xd4, 0x26, 0x55, 0x95, - 0xad, 0xef, 0xfb, 0xfe, 0x58, 0x86, 0xd7, 0x9e, 0xf4, 0x00, - 0x8d, 0x8c, 0x2a, 0x0c, 0xbd, 0x42, 0x04, 0xce, 0xa7, 0x3f, - 0x04, 0xf6, 0xee, 0x80, 0xf2, 0xaa, 0xef, 0x52, 0xa1, 0x69, - 0x66, 0xda, 0xbe, 0x1a, 0xad, 0x5d, 0xda, 0x2c, 0x66, 0xea, - 0x1a, 0x6b, 0xbb, 0xe5, 0x1a, 0x51, 0x4a, 0x00, 0x2f, 0x48, - 0xc7, 0x98, 0x75, 0xd8, 0xb9, 0x29, 0xc8, 0xee, 0xf8, 0x66, - 0x6d, 0x0a, 0x9c, 0xb3, 0xf3, 0xfc, 0x78, 0x7c, 0xa2, 0xf8, - 0xa3, 0xf2, 0xb5, 0xc3, 0xf3, 0xb9, 0x7a, 0x91, 0xc1, 0xa7, - 0xe6, 0x25, 0x2e, 0x9c, 0xa8, 0xed, 0x12, 0x65, 0x6e, 0x6a, - 0xf6, 0x12, 0x44, 0x53, 0x70, 0x30, 0x95, 0xc3, 0x9c, 0x2b, - 0x58, 0x2b, 0x3d, 0x08, 0x74, 0x4a, 0xf2, 0xbe, 0x51, 0xb0, - 0xbf, 0x87, 0xd0, 0x4c, 0x27, 0x58, 0x6b, 0xb5, 0x35, 0xc5, - 0x9d, 0xaf, 0x17, 0x31, 0xf8, 0x0b, 0x8f, 0xee, 0xad, 0x81, - 0x36, 0x05, 0x89, 0x08, 0x98, 0xcf, 0x3a, 0xaf, 0x25, 0x87, - 0xc0, 0x49, 0xea, 0xa7, 0xfd, 0x67, 0xf7, 0x45, 0x8e, 0x97, - 0xcc, 0x14, 0x39, 0xe2, 0x36, 0x85, 0xb5, 0x7e, 0x1a, 0x37, - 0xfd, 0x16, 0xf6, 0x71, 0x11, 0x9a, 0x74, 0x30, 0x16, 0xfe, - 0x13, 0x94, 0xa3, 0x3f, 0x84, 0x0d, 0x4f, - // public exponent - 0x02, 0x03, // an INTEGER of length 3 - 0x01, 0x00, 0x01 - }; - - // We use the signature verifier to perform four signature verification - // tests. - base::SignatureVerifier verifier; - bool ok; - - // Test 1: feed all of the data to the verifier at once (a single - // VerifyUpdate call). - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); - EXPECT_TRUE(ok); - verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate)); - ok = verifier.VerifyFinal(); - EXPECT_TRUE(ok); - - // Test 2: feed the data to the verifier in three parts (three VerifyUpdate - // calls). - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); - EXPECT_TRUE(ok); - verifier.VerifyUpdate(tbs_certificate, 256); - verifier.VerifyUpdate(tbs_certificate + 256, 256); - verifier.VerifyUpdate(tbs_certificate + 512, sizeof(tbs_certificate) - 512); - ok = verifier.VerifyFinal(); - EXPECT_TRUE(ok); - - // Test 3: verify the signature with incorrect data. - uint8 bad_tbs_certificate[sizeof(tbs_certificate)]; - memcpy(bad_tbs_certificate, tbs_certificate, sizeof(tbs_certificate)); - bad_tbs_certificate[10] += 1; // Corrupt one byte of the data. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); - EXPECT_TRUE(ok); - verifier.VerifyUpdate(bad_tbs_certificate, sizeof(bad_tbs_certificate)); - ok = verifier.VerifyFinal(); - - // Purify disables digital signature verification, causing the Windows - // CryptoAPI function CryptVerifySignature to always succeed. So we can't - // check the signature verification results of the negative tests when - // running inside Purify. See http://crbug.com/10031. -#ifndef PURIFY - EXPECT_FALSE(ok); -#endif - - // Test 4: verify a bad signature. - uint8 bad_signature[sizeof(signature)]; - memcpy(bad_signature, signature, sizeof(signature)); - bad_signature[10] += 1; // Corrupt one byte of the signature. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - bad_signature, sizeof(bad_signature), - public_key_info, sizeof(public_key_info)); - - // A crypto library (e.g., NSS) may detect that the signature is corrupted - // and cause VerifyInit to return false, so it is fine for 'ok' to be false. - if (ok) { - verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate)); - ok = verifier.VerifyFinal(); -#ifndef PURIFY - EXPECT_FALSE(ok); -#endif - } -} diff --git a/base/crypto/signature_verifier_win.cc b/base/crypto/signature_verifier_win.cc deleted file mode 100644 index c040d05..0000000 --- a/base/crypto/signature_verifier_win.cc +++ /dev/null @@ -1,134 +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/crypto/signature_verifier.h" - -#include "base/logging.h" - -#pragma comment(lib, "crypt32.lib") - -namespace { - -// Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the -// WINAPI calling convention. -void* WINAPI MyCryptAlloc(size_t size) { - return malloc(size); -} - -void WINAPI MyCryptFree(void* p) { - free(p); -} - -} // namespace - -namespace base { - -SignatureVerifier::SignatureVerifier() : hash_object_(0), public_key_(0) { - if (!CryptAcquireContext(provider_.receive(), NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - provider_.reset(); -} - -SignatureVerifier::~SignatureVerifier() { -} - -bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - signature_.reserve(signature_len); - // CryptoAPI uses big integers in the little-endian byte order, so we need - // to first swap the order of signature bytes. - for (int i = signature_len - 1; i >= 0; --i) - signature_.push_back(signature[i]); - - CRYPT_DECODE_PARA decode_para; - decode_para.cbSize = sizeof(decode_para); - decode_para.pfnAlloc = MyCryptAlloc; - decode_para.pfnFree = MyCryptFree; - CERT_PUBLIC_KEY_INFO* cert_public_key_info = NULL; - DWORD struct_len = 0; - BOOL ok; - ok = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - X509_PUBLIC_KEY_INFO, - public_key_info, - public_key_info_len, - CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, - &decode_para, - &cert_public_key_info, - &struct_len); - if (!ok) - return false; - - ok = CryptImportPublicKeyInfo(provider_, - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - cert_public_key_info, public_key_.receive()); - free(cert_public_key_info); - if (!ok) - return false; - - CRYPT_ALGORITHM_IDENTIFIER* signature_algorithm_id; - struct_len = 0; - ok = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - X509_ALGORITHM_IDENTIFIER, - signature_algorithm, - signature_algorithm_len, - CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, - &decode_para, - &signature_algorithm_id, - &struct_len); - DCHECK(ok || GetLastError() == ERROR_FILE_NOT_FOUND); - ALG_ID hash_alg_id; - if (ok) { - hash_alg_id = CALG_MD4; // Initialize to a weak hash algorithm that we - // don't support. - if (!strcmp(signature_algorithm_id->pszObjId, szOID_RSA_SHA1RSA)) - hash_alg_id = CALG_SHA1; - else if (!strcmp(signature_algorithm_id->pszObjId, szOID_RSA_MD5RSA)) - hash_alg_id = CALG_MD5; - free(signature_algorithm_id); - DCHECK(hash_alg_id != CALG_MD4); - if (hash_alg_id == CALG_MD4) - return false; // Unsupported hash algorithm. - } else if (GetLastError() == ERROR_FILE_NOT_FOUND) { - // TODO(wtc): X509_ALGORITHM_IDENTIFIER isn't supported on XP SP2. We - // may be able to encapsulate signature_algorithm in a dummy SignedContent - // and decode it with X509_CERT into a CERT_SIGNED_CONTENT_INFO. For now, - // just hardcode the hash algorithm to be SHA-1. - hash_alg_id = CALG_SHA1; - } else { - return false; - } - - ok = CryptCreateHash(provider_, hash_alg_id, 0, 0, hash_object_.receive()); - if (!ok) - return false; - return true; -} - -void SignatureVerifier::VerifyUpdate(const uint8* data_part, - int data_part_len) { - BOOL ok = CryptHashData(hash_object_, data_part, data_part_len, 0); - DCHECK(ok) << "CryptHashData failed: " << GetLastError(); -} - -bool SignatureVerifier::VerifyFinal() { - BOOL ok = CryptVerifySignature(hash_object_, &signature_[0], - signature_.size(), public_key_, NULL, 0); - Reset(); - if (!ok) - return false; - return true; -} - -void SignatureVerifier::Reset() { - hash_object_.reset(); - public_key_.reset(); - signature_.clear(); -} - -} // namespace base - diff --git a/base/crypto/symmetric_key.h b/base/crypto/symmetric_key.h deleted file mode 100644 index ce98fa6..0000000 --- a/base/crypto/symmetric_key.h +++ /dev/null @@ -1,104 +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_CRYPTO_SYMMETRIC_KEY_H_ -#define BASE_CRYPTO_SYMMETRIC_KEY_H_ -#pragma once - -#include <string> - -#include "base/basictypes.h" - -#if defined(USE_NSS) -#include "base/crypto/scoped_nss_types.h" -#elif defined(OS_MACOSX) -#include <Security/cssmtype.h> -#elif defined(OS_WIN) -#include "base/crypto/scoped_capi_types.h" -#endif - -namespace base { - -// Wraps a platform-specific symmetric key and allows it to be held in a -// scoped_ptr. -class SymmetricKey { - public: - // Defines the algorithm that a key will be used with. See also - // classs Encrptor. - enum Algorithm { - AES, - HMAC_SHA1, - }; - - virtual ~SymmetricKey(); - - // Generates a random key suitable to be used with |algorithm| and of - // |key_size_in_bits| bits. - // The caller is responsible for deleting the returned SymmetricKey. - static SymmetricKey* GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits); - - // Derives a key from the supplied password and salt using PBKDF2, suitable - // for use with specified |algorithm|. Note |algorithm| is not the algorithm - // used to derive the key from the password. The caller is responsible for - // deleting the returned SymmetricKey. - static SymmetricKey* DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits); - - // Imports an array of key bytes in |raw_key|. This key may have been - // generated by GenerateRandomKey or DeriveKeyFromPassword and exported with - // GetRawKey, or via another compatible method. The key must be of suitable - // size for use with |algorithm|. The caller owns the returned SymmetricKey. - static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key); - -#if defined(USE_OPENSSL) - const std::string& key() { return key_; } -#elif defined(USE_NSS) - PK11SymKey* key() const { return key_.get(); } -#elif defined(OS_MACOSX) - CSSM_DATA cssm_data() const; -#elif defined(OS_WIN) - HCRYPTKEY key() const { return key_.get(); } -#endif - - // Extracts the raw key from the platform specific data. - // Warning: |raw_key| holds the raw key as bytes and thus must be handled - // carefully. - bool GetRawKey(std::string* raw_key); - - private: -#if defined(USE_OPENSSL) - SymmetricKey() {} - std::string key_; -#elif defined(USE_NSS) - explicit SymmetricKey(PK11SymKey* key); - ScopedPK11SymKey key_; -#elif defined(OS_MACOSX) - SymmetricKey(const void* key_data, size_t key_size_in_bits); - std::string key_; -#elif defined(OS_WIN) - SymmetricKey(HCRYPTPROV provider, HCRYPTKEY key, - const void* key_data, size_t key_size_in_bytes); - - ScopedHCRYPTPROV provider_; - ScopedHCRYPTKEY key_; - - // Contains the raw key, if it is known during initialization and when it - // is likely that the associated |provider_| will be unable to export the - // |key_|. This is the case of HMAC keys when the key size exceeds 16 bytes - // when using the default RSA provider. - // TODO(rsleevi): See if KP_EFFECTIVE_KEYLEN is the reason why CryptExportKey - // fails with NTE_BAD_KEY/NTE_BAD_LEN - std::string raw_key_; -#endif - - DISALLOW_COPY_AND_ASSIGN(SymmetricKey); -}; - -} // namespace base - -#endif // BASE_CRYPTO_SYMMETRIC_KEY_H_ diff --git a/base/crypto/symmetric_key_mac.cc b/base/crypto/symmetric_key_mac.cc deleted file mode 100644 index 574f9d2..0000000 --- a/base/crypto/symmetric_key_mac.cc +++ /dev/null @@ -1,155 +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/crypto/symmetric_key.h" - -#include <CommonCrypto/CommonCryptor.h> -#include <CoreFoundation/CFString.h> -#include <Security/cssm.h> - -#include "base/crypto/cssm_init.h" -#include "base/logging.h" - -namespace { - -CSSM_KEY_TYPE CheckKeyParams(base::SymmetricKey::Algorithm algorithm, - size_t key_size_in_bits) { - if (algorithm == base::SymmetricKey::AES) { - CHECK(key_size_in_bits == 128 || - key_size_in_bits == 192 || - key_size_in_bits == 256) - << "Invalid key size " << key_size_in_bits << " bits"; - return CSSM_ALGID_AES; - } else { - // FIPS 198 Section 3 requires a HMAC-SHA-1 derived keys to be at least - // (HMAC-SHA-1 output size / 2) to be compliant. Since the ouput size of - // HMAC-SHA-1 is 160 bits, we require at least 80 bits here. - CHECK(algorithm == base::SymmetricKey::HMAC_SHA1); - CHECK(key_size_in_bits >= 80 && (key_size_in_bits % 8) == 0) - << "Invalid key size " << key_size_in_bits << " bits"; - return CSSM_ALGID_SHA1HMAC_LEGACY; - } -} - -void* CreateRandomBytes(size_t size) { - CSSM_RETURN err; - CSSM_CC_HANDLE ctx; - err = CSSM_CSP_CreateRandomGenContext(base::GetSharedCSPHandle(), - CSSM_ALGID_APPLE_YARROW, - NULL, - size, &ctx); - if (err) { - base::LogCSSMError("CSSM_CSP_CreateRandomGenContext", err); - return NULL; - } - CSSM_DATA random_data = {}; - err = CSSM_GenerateRandom(ctx, &random_data); - if (err) { - base::LogCSSMError("CSSM_GenerateRandom", err); - random_data.Data = NULL; - } - CSSM_DeleteContext(ctx); - return random_data.Data; // Caller responsible for freeing this -} - -inline CSSM_DATA StringToData(const std::string& str) { - CSSM_DATA data = { - str.size(), - reinterpret_cast<uint8_t*>(const_cast<char*>(str.data())) - }; - return data; -} - -} // namespace - -namespace base { - -SymmetricKey::~SymmetricKey() {} - -// static -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits) { - CheckKeyParams(algorithm, key_size_in_bits); - void* random_bytes = CreateRandomBytes((key_size_in_bits + 7) / 8); - if (!random_bytes) - return NULL; - SymmetricKey *key = new SymmetricKey(random_bytes, key_size_in_bits); - free(random_bytes); - return key; -} - -// static -SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits) { - // Derived (haha) from cdsaDeriveKey() in Apple's CryptoSample. - CSSM_KEY_TYPE key_type = CheckKeyParams(algorithm, key_size_in_bits); - SymmetricKey* derived_key = NULL; - CSSM_KEY cssm_key = {}; - - CSSM_CC_HANDLE ctx = 0; - CSSM_ACCESS_CREDENTIALS credentials = {}; - CSSM_RETURN err; - CSSM_DATA salt_data = StringToData(salt); - err = CSSM_CSP_CreateDeriveKeyContext(GetSharedCSPHandle(), - CSSM_ALGID_PKCS5_PBKDF2, - key_type, key_size_in_bits, - &credentials, - NULL, - iterations, - &salt_data, - NULL, - &ctx); - if (err) { - LogCSSMError("CSSM_CSP_CreateDeriveKeyContext", err); - return NULL; - } - - CSSM_PKCS5_PBKDF2_PARAMS params = {}; - params.Passphrase = StringToData(password); - params.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; - CSSM_DATA param_data = {sizeof(params), reinterpret_cast<uint8_t*>(¶ms)}; - err = CSSM_DeriveKey(ctx, - ¶m_data, - CSSM_KEYUSE_ANY, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - NULL, - NULL, - &cssm_key); - if (err) { - LogCSSMError("CSSM_DeriveKey", err); - goto exit; - } - - DCHECK_EQ(cssm_key.KeyData.Length, key_size_in_bits / 8); - derived_key = new SymmetricKey(cssm_key.KeyData.Data, key_size_in_bits); - - exit: - CSSM_DeleteContext(ctx); - CSSM_FreeKey(GetSharedCSPHandle(), &credentials, &cssm_key, false); - return derived_key; -} - -// static -SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const std::string& raw_key) { - return new SymmetricKey(raw_key.data(), raw_key.size() * 8); -} - -SymmetricKey::SymmetricKey(const void *key_data, size_t key_size_in_bits) - : key_(reinterpret_cast<const char*>(key_data), - key_size_in_bits / 8) {} - -bool SymmetricKey::GetRawKey(std::string* raw_key) { - *raw_key = key_; - return true; -} - -CSSM_DATA SymmetricKey::cssm_data() const { - return StringToData(key_); -} - -} // namespace base diff --git a/base/crypto/symmetric_key_nss.cc b/base/crypto/symmetric_key_nss.cc deleted file mode 100644 index 1e3551d..0000000 --- a/base/crypto/symmetric_key_nss.cc +++ /dev/null @@ -1,127 +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/crypto/symmetric_key.h" - -#include <nss.h> -#include <pk11pub.h> - -#include "base/nss_util.h" -#include "base/logging.h" - -namespace base { - -SymmetricKey::~SymmetricKey() {} - -// static -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits) { - DCHECK_EQ(AES, algorithm); - - EnsureNSSInit(); - if (key_size_in_bits == 0) - return NULL; - - ScopedPK11Slot slot(PK11_GetBestSlot(CKM_AES_KEY_GEN, NULL)); - if (!slot.get()) - return NULL; - - PK11SymKey* sym_key = PK11_KeyGen(slot.get(), CKM_AES_KEY_GEN, NULL, - key_size_in_bits / 8, NULL); - if (!sym_key) - return NULL; - - return new SymmetricKey(sym_key); -} - -// static -SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits) { - EnsureNSSInit(); - if (salt.empty() || iterations == 0 || key_size_in_bits == 0) - return NULL; - - SECItem password_item; - password_item.type = siBuffer; - password_item.data = reinterpret_cast<unsigned char*>( - const_cast<char *>(password.data())); - password_item.len = password.size(); - - SECItem salt_item; - salt_item.type = siBuffer; - salt_item.data = reinterpret_cast<unsigned char*>( - const_cast<char *>(salt.data())); - salt_item.len = salt.size(); - - SECOidTag cipher_algorithm = - algorithm == AES ? SEC_OID_AES_256_CBC : SEC_OID_HMAC_SHA1; - ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, - cipher_algorithm, - SEC_OID_HMAC_SHA1, - key_size_in_bits / 8, - iterations, - &salt_item)); - if (!alg_id.get()) - return NULL; - - ScopedPK11Slot slot(PK11_GetBestSlot(SEC_OID_PKCS5_PBKDF2, NULL)); - if (!slot.get()) - return NULL; - - PK11SymKey* sym_key = PK11_PBEKeyGen(slot.get(), alg_id.get(), &password_item, - PR_FALSE, NULL); - if (!sym_key) - return NULL; - - return new SymmetricKey(sym_key); -} - -// static -SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const std::string& raw_key) { - CK_MECHANISM_TYPE cipher = - algorithm == AES ? CKM_AES_CBC : CKM_SHA_1_HMAC; - - SECItem key_item; - key_item.type = siBuffer; - key_item.data = reinterpret_cast<unsigned char*>( - const_cast<char *>(raw_key.data())); - key_item.len = raw_key.size(); - - ScopedPK11Slot slot(PK11_GetBestSlot(cipher, NULL)); - if (!slot.get()) - return NULL; - - // The exact value of the |origin| argument doesn't matter to NSS as long as - // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a - // placeholder. - PK11SymKey* sym_key = PK11_ImportSymKey(slot.get(), cipher, PK11_OriginUnwrap, - CKA_ENCRYPT, &key_item, NULL); - if (!sym_key) - return NULL; - - return new SymmetricKey(sym_key); -} - -bool SymmetricKey::GetRawKey(std::string* raw_key) { - SECStatus rv = PK11_ExtractKeyValue(key_.get()); - if (SECSuccess != rv) - return false; - - SECItem* key_item = PK11_GetKeyData(key_.get()); - if (!key_item) - return false; - - raw_key->assign(reinterpret_cast<char*>(key_item->data), key_item->len); - return true; -} - -SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) { - DCHECK(key); -} - -} // namespace base diff --git a/base/crypto/symmetric_key_openssl.cc b/base/crypto/symmetric_key_openssl.cc deleted file mode 100644 index 409cce4..0000000 --- a/base/crypto/symmetric_key_openssl.cc +++ /dev/null @@ -1,76 +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/crypto/symmetric_key.h" - -#include <openssl/evp.h> -#include <openssl/rand.h> - -#include <algorithm> - -#include "base/logging.h" -#include "base/openssl_util.h" -#include "base/scoped_ptr.h" -#include "base/string_util.h" - -namespace base { - -SymmetricKey::~SymmetricKey() { - std::fill(key_.begin(), key_.end(), '\0'); // Zero out the confidential key. -} - -// static -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits) { - DCHECK_EQ(AES, algorithm); - int key_size_in_bytes = key_size_in_bits / 8; - DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8); - - if (key_size_in_bits == 0) - return NULL; - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - scoped_ptr<SymmetricKey> key(new SymmetricKey); - uint8* key_data = - reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1)); - - int rv = RAND_bytes(key_data, key_size_in_bytes); - return rv == 1 ? key.release() : NULL; -} - -// static -SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits) { - DCHECK(algorithm == AES || algorithm == HMAC_SHA1); - int key_size_in_bytes = key_size_in_bits / 8; - DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8); - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - scoped_ptr<SymmetricKey> key(new SymmetricKey); - uint8* key_data = - reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1)); - int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(), - reinterpret_cast<const uint8*>(salt.data()), - salt.length(), iterations, - key_size_in_bytes, key_data); - return rv == 1 ? key.release() : NULL; -} - -// static -SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const std::string& raw_key) { - scoped_ptr<SymmetricKey> key(new SymmetricKey); - key->key_ = raw_key; - return key.release(); -} - -bool SymmetricKey::GetRawKey(std::string* raw_key) { - *raw_key = key_; - return true; -} - -} // namespace base diff --git a/base/crypto/symmetric_key_unittest.cc b/base/crypto/symmetric_key_unittest.cc deleted file mode 100644 index a9b0b9e..0000000 --- a/base/crypto/symmetric_key_unittest.cc +++ /dev/null @@ -1,226 +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/crypto/symmetric_key.h" - -#include <string> - -#include "base/scoped_ptr.h" -#include "base/string_number_conversions.h" -#include "base/string_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(SymmetricKeyTest, GenerateRandomKey) { - scoped_ptr<base::SymmetricKey> key( - base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); - ASSERT_TRUE(NULL != key.get()); - std::string raw_key; - EXPECT_TRUE(key->GetRawKey(&raw_key)); - EXPECT_EQ(32U, raw_key.size()); - - // Do it again and check that the keys are different. - // (Note: this has a one-in-10^77 chance of failure!) - scoped_ptr<base::SymmetricKey> key2( - base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); - ASSERT_TRUE(NULL != key2.get()); - std::string raw_key2; - EXPECT_TRUE(key2->GetRawKey(&raw_key2)); - EXPECT_EQ(32U, raw_key2.size()); - EXPECT_NE(raw_key, raw_key2); -} - -TEST(SymmetricKeyTest, ImportGeneratedKey) { - scoped_ptr<base::SymmetricKey> key1( - base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); - ASSERT_TRUE(NULL != key1.get()); - std::string raw_key1; - EXPECT_TRUE(key1->GetRawKey(&raw_key1)); - - scoped_ptr<base::SymmetricKey> key2( - base::SymmetricKey::Import(base::SymmetricKey::AES, raw_key1)); - ASSERT_TRUE(NULL != key2.get()); - - std::string raw_key2; - EXPECT_TRUE(key2->GetRawKey(&raw_key2)); - - EXPECT_EQ(raw_key1, raw_key2); -} - -TEST(SymmetricKeyTest, ImportDerivedKey) { - scoped_ptr<base::SymmetricKey> key1( - base::SymmetricKey::DeriveKeyFromPassword(base::SymmetricKey::HMAC_SHA1, - "password", "somesalt", 1024, - 160)); - ASSERT_TRUE(NULL != key1.get()); - std::string raw_key1; - EXPECT_TRUE(key1->GetRawKey(&raw_key1)); - - scoped_ptr<base::SymmetricKey> key2( - base::SymmetricKey::Import(base::SymmetricKey::HMAC_SHA1, raw_key1)); - ASSERT_TRUE(NULL != key2.get()); - - std::string raw_key2; - EXPECT_TRUE(key2->GetRawKey(&raw_key2)); - - EXPECT_EQ(raw_key1, raw_key2); -} - -struct PBKDF2TestVector { - base::SymmetricKey::Algorithm algorithm; - const char* password; - const char* salt; - unsigned int rounds; - unsigned int key_size_in_bits; - const char* expected; // ASCII encoded hex bytes -}; - -class SymmetricKeyDeriveKeyFromPasswordTest - : public testing::TestWithParam<PBKDF2TestVector> { -}; - -TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) { - PBKDF2TestVector test_data(GetParam()); -#if defined(OS_MACOSX) - // The OS X crypto libraries have minimum salt and iteration requirements - // so some of the tests below will cause them to barf. Skip these. - if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) { - VLOG(1) << "Skipped test vector for " << test_data.expected; - return; - } -#endif // OS_MACOSX - - scoped_ptr<base::SymmetricKey> key( - base::SymmetricKey::DeriveKeyFromPassword( - test_data.algorithm, - test_data.password, test_data.salt, - test_data.rounds, test_data.key_size_in_bits)); - ASSERT_TRUE(NULL != key.get()); - - std::string raw_key; - key->GetRawKey(&raw_key); - EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size()); - EXPECT_EQ(test_data.expected, - StringToLowerASCII(base::HexEncode(raw_key.data(), - raw_key.size()))); -} - -static const PBKDF2TestVector kTestVectors[] = { - // These tests come from - // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt - { - base::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 1, - 160, - "0c60c80f961f0e71f3a9b524af6012062fe037a6", - }, - { - base::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 2, - 160, - "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", - }, - { - base::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 4096, - 160, - "4b007901b765489abead49d926f721d065a429c1", - }, - // This test takes over 30s to run on the trybots. -#if 0 - { - base::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 16777216, - 160, - "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984", - }, -#endif - - // These tests come from RFC 3962, via BSD source code at - // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain - { - base::SymmetricKey::HMAC_SHA1, - "password", - "ATHENA.MIT.EDUraeburn", - 1, - 160, - "cdedb5281bb2f801565a1122b25635150ad1f7a0", - }, - { - base::SymmetricKey::HMAC_SHA1, - "password", - "ATHENA.MIT.EDUraeburn", - 2, - 160, - "01dbee7f4a9e243e988b62c73cda935da05378b9", - }, - { - base::SymmetricKey::HMAC_SHA1, - "password", - "ATHENA.MIT.EDUraeburn", - 1200, - 160, - "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb", - }, - { - base::SymmetricKey::HMAC_SHA1, - "password", - "\0224VxxV4\022", /* 0x1234567878563412 */ - 5, - 160, - "d1daa78615f287e6a1c8b120d7062a493f98d203", - }, - { - base::SymmetricKey::HMAC_SHA1, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "pass phrase equals block size", - 1200, - 160, - "139c30c0966bc32ba55fdbf212530ac9c5ec59f1", - }, - { - base::SymmetricKey::HMAC_SHA1, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "pass phrase exceeds block size", - 1200, - 160, - "9ccad6d468770cd51b10e6a68721be611a8b4d28", - }, - { - base::SymmetricKey::HMAC_SHA1, - "\360\235\204\236", /* g-clef (0xf09d849e) */ - "EXAMPLE.COMpianist", - 50, - 160, - "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0", - }, - - // Regression tests for AES keys, derived from the Linux NSS implementation. - { - base::SymmetricKey::AES, - "A test password", - "saltsalt", - 1, - 256, - "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de", - }, - { - base::SymmetricKey::AES, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "pass phrase exceeds block size", - 20, - 256, - "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c", - }, -}; - -INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest, - testing::ValuesIn(kTestVectors)); diff --git a/base/crypto/symmetric_key_win.cc b/base/crypto/symmetric_key_win.cc deleted file mode 100644 index 87d715a..0000000 --- a/base/crypto/symmetric_key_win.cc +++ /dev/null @@ -1,536 +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/crypto/symmetric_key.h" - -#include <winsock2.h> // For htonl. - -#include <vector> - -// TODO(wtc): replace scoped_array by std::vector. -#include "base/scoped_ptr.h" - -namespace base { - -namespace { - -// The following is a non-public Microsoft header documented in MSDN under -// CryptImportKey / CryptExportKey. Following the header is the byte array of -// the actual plaintext key. -struct PlaintextBlobHeader { - BLOBHEADER hdr; - DWORD cbKeySize; -}; - -// CryptoAPI makes use of three distinct ALG_IDs for AES, rather than just -// CALG_AES (which exists, but depending on the functions you are calling, may -// result in function failure, whereas the subtype would succeed). -ALG_ID GetAESAlgIDForKeySize(size_t key_size_in_bits) { - // Only AES-128/-192/-256 is supported in CryptoAPI. - switch (key_size_in_bits) { - case 128: - return CALG_AES_128; - case 192: - return CALG_AES_192; - case 256: - return CALG_AES_256; - default: - NOTREACHED(); - return 0; - } -}; - -// Imports a raw/plaintext key of |key_size| stored in |*key_data| into a new -// key created for the specified |provider|. |alg| contains the algorithm of -// the key being imported. -// If |key_data| is intended to be used as an HMAC key, then |alg| should be -// CALG_HMAC. -// If successful, returns true and stores the imported key in |*key|. -// TODO(wtc): use this function in hmac_win.cc. -bool ImportRawKey(HCRYPTPROV provider, - ALG_ID alg, - const void* key_data, DWORD key_size, - ScopedHCRYPTKEY* key) { - DCHECK_GT(key_size, 0); - - DWORD actual_size = sizeof(PlaintextBlobHeader) + key_size; - std::vector<BYTE> tmp_data(actual_size); - BYTE* actual_key = &tmp_data[0]; - memcpy(actual_key + sizeof(PlaintextBlobHeader), key_data, key_size); - PlaintextBlobHeader* key_header = - reinterpret_cast<PlaintextBlobHeader*>(actual_key); - memset(key_header, 0, sizeof(PlaintextBlobHeader)); - - key_header->hdr.bType = PLAINTEXTKEYBLOB; - key_header->hdr.bVersion = CUR_BLOB_VERSION; - key_header->hdr.aiKeyAlg = alg; - - key_header->cbKeySize = key_size; - - HCRYPTKEY unsafe_key = NULL; - DWORD flags = CRYPT_EXPORTABLE; - if (alg == CALG_HMAC) { - // Though it may appear odd that IPSEC and RC2 are being used, this is - // done in accordance with Microsoft's FIPS 140-2 Security Policy for the - // RSA Enhanced Provider, as the approved means of using arbitrary HMAC - // key material. - key_header->hdr.aiKeyAlg = CALG_RC2; - flags |= CRYPT_IPSEC_HMAC_KEY; - } - - BOOL ok = - CryptImportKey(provider, actual_key, actual_size, 0, flags, &unsafe_key); - - // Clean up the temporary copy of key, regardless of whether it was imported - // sucessfully or not. - SecureZeroMemory(actual_key, actual_size); - - if (!ok) - return false; - - key->reset(unsafe_key); - return true; -} - -// Attempts to generate a random AES key of |key_size_in_bits|. Returns true -// if generation is successful, storing the generated key in |*key| and the -// key provider (CSP) in |*provider|. -bool GenerateAESKey(size_t key_size_in_bits, - ScopedHCRYPTPROV* provider, - ScopedHCRYPTKEY* key) { - DCHECK(provider); - DCHECK(key); - - ALG_ID alg = GetAESAlgIDForKeySize(key_size_in_bits); - if (alg == 0) - return false; - - ScopedHCRYPTPROV safe_provider; - // Note: The only time NULL is safe to be passed as pszContainer is when - // dwFlags contains CRYPT_VERIFYCONTEXT, as all keys generated and/or used - // will be treated as ephemeral keys and not persisted. - BOOL ok = CryptAcquireContext(safe_provider.receive(), NULL, NULL, - PROV_RSA_AES, CRYPT_VERIFYCONTEXT); - if (!ok) - return false; - - ScopedHCRYPTKEY safe_key; - // In the FIPS 140-2 Security Policy for CAPI on XP/Vista+, Microsoft notes - // that CryptGenKey makes use of the same functionality exposed via - // CryptGenRandom. The reason this is being used, as opposed to - // CryptGenRandom and CryptImportKey is for compliance with the security - // policy - ok = CryptGenKey(safe_provider.get(), alg, CRYPT_EXPORTABLE, - safe_key.receive()); - if (!ok) - return false; - - key->swap(safe_key); - provider->swap(safe_provider); - - return true; -} - -// Returns true if the HMAC key size meets the requirement of FIPS 198 -// Section 3. |alg| is the hash function used in the HMAC. -bool CheckHMACKeySize(size_t key_size_in_bits, ALG_ID alg) { - DWORD hash_size = 0; - switch (alg) { - case CALG_SHA1: - hash_size = 20; - break; - case CALG_SHA_256: - hash_size = 32; - break; - case CALG_SHA_384: - hash_size = 48; - break; - case CALG_SHA_512: - hash_size = 64; - break; - } - if (hash_size == 0) - return false; - - // An HMAC key must be >= L/2, where L is the output size of the hash - // function being used. - return (key_size_in_bits >= (hash_size / 2 * 8) && - (key_size_in_bits % 8) == 0); -} - -// Attempts to generate a random, |key_size_in_bits|-long HMAC key, for use -// with the hash function |alg|. -// |key_size_in_bits| must be >= 1/2 the hash size of |alg| for security. -// Returns true if generation is successful, storing the generated key in -// |*key| and the key provider (CSP) in |*provider|. -bool GenerateHMACKey(size_t key_size_in_bits, - ALG_ID alg, - ScopedHCRYPTPROV* provider, - ScopedHCRYPTKEY* key, - scoped_array<BYTE>* raw_key) { - DCHECK(provider); - DCHECK(key); - DCHECK(raw_key); - - if (!CheckHMACKeySize(key_size_in_bits, alg)) - return false; - - ScopedHCRYPTPROV safe_provider; - // See comment in GenerateAESKey as to why NULL is acceptable for the - // container name. - BOOL ok = CryptAcquireContext(safe_provider.receive(), NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - if (!ok) - return false; - - DWORD key_size_in_bytes = key_size_in_bits / 8; - scoped_array<BYTE> random(new BYTE[key_size_in_bytes]); - ok = CryptGenRandom(safe_provider, key_size_in_bytes, random.get()); - if (!ok) - return false; - - ScopedHCRYPTKEY safe_key; - bool rv = ImportRawKey(safe_provider, CALG_HMAC, random.get(), - key_size_in_bytes, &safe_key); - if (rv) { - key->swap(safe_key); - provider->swap(safe_provider); - raw_key->swap(random); - } - - SecureZeroMemory(random.get(), key_size_in_bytes); - return rv; -} - -// Attempts to create an HMAC hash instance using the specified |provider| -// and |key|. The inner hash function will be |hash_alg|. If successful, -// returns true and stores the hash in |*hash|. -// TODO(wtc): use this function in hmac_win.cc. -bool CreateHMACHash(HCRYPTPROV provider, - HCRYPTKEY key, - ALG_ID hash_alg, - ScopedHCRYPTHASH* hash) { - ScopedHCRYPTHASH safe_hash; - BOOL ok = CryptCreateHash(provider, CALG_HMAC, key, 0, safe_hash.receive()); - if (!ok) - return false; - - HMAC_INFO hmac_info; - memset(&hmac_info, 0, sizeof(hmac_info)); - hmac_info.HashAlgid = hash_alg; - - ok = CryptSetHashParam(safe_hash, HP_HMAC_INFO, - reinterpret_cast<const BYTE*>(&hmac_info), 0); - if (!ok) - return false; - - hash->swap(safe_hash); - return true; -} - -// Computes a block of the derived key using the PBKDF2 function F for the -// specified |block_index| using the PRF |hash|, writing the output to -// |output_buf|. -// |output_buf| must have enough space to accomodate the output of the PRF -// specified by |hash|. -// Returns true if the block was successfully computed. -bool ComputePBKDF2Block(HCRYPTHASH hash, - DWORD hash_size, - const std::string& salt, - size_t iterations, - uint32 block_index, - BYTE* output_buf) { - // From RFC 2898: - // 3. <snip> The function F is defined as the exclusive-or sum of the first - // c iterates of the underlying pseudorandom function PRF applied to the - // password P and the concatenation of the salt S and the block index i: - // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c - // where - // U_1 = PRF(P, S || INT (i)) - // U_2 = PRF(P, U_1) - // ... - // U_c = PRF(P, U_{c-1}) - ScopedHCRYPTHASH safe_hash; - BOOL ok = CryptDuplicateHash(hash, NULL, 0, safe_hash.receive()); - if (!ok) - return false; - - // Iteration U_1: Compute PRF for S. - ok = CryptHashData(safe_hash, reinterpret_cast<const BYTE*>(salt.data()), - salt.size(), 0); - if (!ok) - return false; - - // Iteration U_1: and append (big-endian) INT (i). - uint32 big_endian_block_index = htonl(block_index); - ok = CryptHashData(safe_hash, - reinterpret_cast<BYTE*>(&big_endian_block_index), - sizeof(big_endian_block_index), 0); - - std::vector<BYTE> hash_value(hash_size); - - DWORD size = hash_size; - ok = CryptGetHashParam(safe_hash, HP_HASHVAL, &hash_value[0], &size, 0); - if (!ok || size != hash_size) - return false; - - memcpy(output_buf, &hash_value[0], hash_size); - - // Iteration 2 - c: Compute U_{iteration} by applying the PRF to - // U_{iteration - 1}, then xor the resultant hash with |output|, which - // contains U_1 ^ U_2 ^ ... ^ U_{iteration - 1}. - for (size_t iteration = 2; iteration <= iterations; ++iteration) { - safe_hash.reset(); - ok = CryptDuplicateHash(hash, NULL, 0, safe_hash.receive()); - if (!ok) - return false; - - ok = CryptHashData(safe_hash, &hash_value[0], hash_size, 0); - if (!ok) - return false; - - size = hash_size; - ok = CryptGetHashParam(safe_hash, HP_HASHVAL, &hash_value[0], &size, 0); - if (!ok || size != hash_size) - return false; - - for (int i = 0; i < hash_size; ++i) - output_buf[i] ^= hash_value[i]; - } - - return true; -} - -} // namespace - -SymmetricKey::~SymmetricKey() { - // TODO(wtc): create a "secure" string type that zeroes itself in the - // destructor. - if (!raw_key_.empty()) - SecureZeroMemory(const_cast<char *>(raw_key_.data()), raw_key_.size()); -} - -// static -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits) { - DCHECK_GE(key_size_in_bits, 8); - - ScopedHCRYPTPROV provider; - ScopedHCRYPTKEY key; - - bool ok = false; - scoped_array<BYTE> raw_key; - - switch (algorithm) { - case AES: - ok = GenerateAESKey(key_size_in_bits, &provider, &key); - break; - case HMAC_SHA1: - ok = GenerateHMACKey(key_size_in_bits, CALG_SHA1, &provider, - &key, &raw_key); - break; - } - - if (!ok) { - NOTREACHED(); - return NULL; - } - - size_t key_size_in_bytes = key_size_in_bits / 8; - if (raw_key == NULL) - key_size_in_bytes = 0; - - SymmetricKey* result = new SymmetricKey(provider.release(), - key.release(), - raw_key.get(), - key_size_in_bytes); - if (raw_key != NULL) - SecureZeroMemory(raw_key.get(), key_size_in_bytes); - - return result; -} - -// static -SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits) { - // CryptoAPI lacks routines to perform PBKDF2 derivation as specified - // in RFC 2898, so it must be manually implemented. Only HMAC-SHA1 is - // supported as the PRF. - - // While not used until the end, sanity-check the input before proceeding - // with the expensive computation. - DWORD provider_type = 0; - ALG_ID alg = 0; - switch (algorithm) { - case AES: - provider_type = PROV_RSA_AES; - alg = GetAESAlgIDForKeySize(key_size_in_bits); - break; - case HMAC_SHA1: - provider_type = PROV_RSA_FULL; - alg = CALG_HMAC; - break; - default: - NOTREACHED(); - break; - } - if (provider_type == 0 || alg == 0) - return NULL; - - ScopedHCRYPTPROV provider; - BOOL ok = CryptAcquireContext(provider.receive(), NULL, NULL, provider_type, - CRYPT_VERIFYCONTEXT); - if (!ok) - return NULL; - - // Convert the user password into a key suitable to be fed into the PRF - // function. - ScopedHCRYPTKEY password_as_key; - BYTE* password_as_bytes = - const_cast<BYTE*>(reinterpret_cast<const BYTE*>(password.data())); - if (!ImportRawKey(provider, CALG_HMAC, password_as_bytes, - password.size(), &password_as_key)) - return NULL; - - // Configure the PRF function. Only HMAC variants are supported, with the - // only hash function supported being SHA1. - // TODO(rsleevi): Support SHA-256 on XP SP3+. - ScopedHCRYPTHASH prf; - if (!CreateHMACHash(provider, password_as_key, CALG_SHA1, &prf)) - return NULL; - - DWORD hLen = 0; - DWORD param_size = sizeof(hLen); - ok = CryptGetHashParam(prf, HP_HASHSIZE, - reinterpret_cast<BYTE*>(&hLen), ¶m_size, 0); - if (!ok || hLen == 0) - return NULL; - - // 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop. - size_t dkLen = key_size_in_bits / 8; - DCHECK_GT(dkLen, 0); - - if ((dkLen / hLen) > 0xFFFFFFFF) { - DLOG(ERROR) << "Derived key too long."; - return NULL; - } - - // 2. Let l be the number of hLen-octet blocks in the derived key, - // rounding up, and let r be the number of octets in the last - // block: - size_t L = (dkLen + hLen - 1) / hLen; - DCHECK_GT(L, 0); - - size_t total_generated_size = L * hLen; - std::vector<BYTE> generated_key(total_generated_size); - BYTE* block_offset = &generated_key[0]; - - // 3. For each block of the derived key apply the function F defined below - // to the password P, the salt S, the iteration count c, and the block - // index to compute the block: - // T_1 = F (P, S, c, 1) - // T_2 = F (P, S, c, 2) - // ... - // T_l = F (P, S, c, l) - // <snip> - // 4. Concatenate the blocks and extract the first dkLen octets to produce - // a derived key DK: - // DK = T_1 || T_2 || ... || T_l<0..r-1> - for (uint32 block_index = 1; block_index <= L; ++block_index) { - if (!ComputePBKDF2Block(prf, hLen, salt, iterations, block_index, - block_offset)) - return NULL; - block_offset += hLen; - } - - // Convert the derived key bytes into a key handle for the desired algorithm. - ScopedHCRYPTKEY key; - if (!ImportRawKey(provider, alg, &generated_key[0], dkLen, &key)) - return NULL; - - SymmetricKey* result = new SymmetricKey(provider.release(), key.release(), - &generated_key[0], dkLen); - - SecureZeroMemory(&generated_key[0], total_generated_size); - - return result; -} - -// static -SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const std::string& raw_key) { - DWORD provider_type = 0; - ALG_ID alg = 0; - switch (algorithm) { - case AES: - provider_type = PROV_RSA_AES; - alg = GetAESAlgIDForKeySize(raw_key.size() * 8); - break; - case HMAC_SHA1: - provider_type = PROV_RSA_FULL; - alg = CALG_HMAC; - break; - default: - NOTREACHED(); - break; - } - if (provider_type == 0 || alg == 0) - return NULL; - - ScopedHCRYPTPROV provider; - BOOL ok = CryptAcquireContext(provider.receive(), NULL, NULL, provider_type, - CRYPT_VERIFYCONTEXT); - if (!ok) - return NULL; - - ScopedHCRYPTKEY key; - if (!ImportRawKey(provider, alg, raw_key.data(), raw_key.size(), &key)) - return NULL; - - return new SymmetricKey(provider.release(), key.release(), - raw_key.data(), raw_key.size()); -} - -bool SymmetricKey::GetRawKey(std::string* raw_key) { - // Short circuit for when the key was supplied to the constructor. - if (!raw_key_.empty()) { - *raw_key = raw_key_; - return true; - } - - DWORD size = 0; - BOOL ok = CryptExportKey(key_, 0, PLAINTEXTKEYBLOB, 0, NULL, &size); - if (!ok) - return false; - - std::vector<BYTE> result(size); - - ok = CryptExportKey(key_, 0, PLAINTEXTKEYBLOB, 0, &result[0], &size); - if (!ok) - return false; - - PlaintextBlobHeader* header = - reinterpret_cast<PlaintextBlobHeader*>(&result[0]); - raw_key->assign(reinterpret_cast<char*>(&result[sizeof(*header)]), - header->cbKeySize); - - SecureZeroMemory(&result[0], size); - - return true; -} - -SymmetricKey::SymmetricKey(HCRYPTPROV provider, - HCRYPTKEY key, - const void* key_data, size_t key_size_in_bytes) - : provider_(provider), key_(key) { - if (key_data) { - raw_key_.assign(reinterpret_cast<const char*>(key_data), - key_size_in_bytes); - } -} - -} // namespace base diff --git a/base/debug/debug_on_start_win.h b/base/debug/debug_on_start_win.h index 5a1081d..4a5c120 100644 --- a/base/debug/debug_on_start_win.h +++ b/base/debug/debug_on_start_win.h @@ -24,6 +24,11 @@ namespace base { namespace debug { +// There is no way for this code, as currently implemented, to work across DLLs. +// TODO(rvargas): It looks like we really don't use this code, at least not for +// Chrome. Figure out if it's really worth implementing something simpler. +#if !defined(BASE_DLL) + // Debug on start functions and data. class DebugOnStart { public: @@ -69,6 +74,8 @@ DECLSPEC_SELECTANY DebugOnStart::PIFV debug_on_start = &DebugOnStart::Init; #endif // _WIN64 +#endif // defined(BASE_DLL) + } // namespace debug } // namespace base diff --git a/base/debug/debugger.h b/base/debug/debugger.h index 77bde0d..bb937a0 100644 --- a/base/debug/debugger.h +++ b/base/debug/debugger.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,16 +10,18 @@ #define BASE_DEBUG_DEBUGGER_H #pragma once +#include "base/base_api.h" + namespace base { namespace debug { // Starts the registered system-wide JIT debugger to attach it to specified // process. -bool SpawnDebuggerOnProcess(unsigned process_id); +BASE_API bool SpawnDebuggerOnProcess(unsigned process_id); // Waits wait_seconds seconds for a debugger to attach to the current process. // When silent is false, an exception is thrown when a debugger is detected. -bool WaitForDebugger(int wait_seconds, bool silent); +BASE_API bool WaitForDebugger(int wait_seconds, bool silent); // Returns true if the given process is being run under a debugger. // @@ -28,18 +30,18 @@ bool WaitForDebugger(int wait_seconds, bool silent); // // WARNING: Because of this, on OS X, a call MUST be made to this function // BEFORE the sandbox is enabled. -bool BeingDebugged(); +BASE_API bool BeingDebugged(); // Break into the debugger, assumes a debugger is present. -void BreakDebugger(); +BASE_API void BreakDebugger(); // Used in test code, this controls whether showing dialogs and breaking into // the debugger is suppressed for debug errors, even in debug mode (normally // release mode doesn't do this stuff -- this is controlled separately). // Normally UI is not suppressed. This is normally used when running automated // tests where we want a crash rather than a dialog or a debugger. -void SetSuppressDebugUI(bool suppress); -bool IsDebugUISuppressed(); +BASE_API void SetSuppressDebugUI(bool suppress); +BASE_API bool IsDebugUISuppressed(); } // namespace debug } // namespace base diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc index 2eacaf9..bf90a0f 100644 --- a/base/debug/debugger_posix.cc +++ b/base/debug/debugger_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,6 +10,7 @@ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <sys/param.h> #include <sys/stat.h> #if !defined(OS_NACL) #include <sys/sysctl.h> @@ -33,8 +34,8 @@ #include "base/basictypes.h" #include "base/eintr_wrapper.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/safe_strerror_posix.h" -#include "base/scoped_ptr.h" #include "base/string_piece.h" #include "base/stringprintf.h" diff --git a/base/debug/leak_tracker_unittest.cc b/base/debug/leak_tracker_unittest.cc index 2e6a9a5..99df4c1 100644 --- a/base/debug/leak_tracker_unittest.cc +++ b/base/debug/leak_tracker_unittest.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/debug/leak_tracker.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc index 5be4c5c..7c44f7a 100644 --- a/base/debug/stack_trace.cc +++ b/base/debug/stack_trace.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,7 +10,7 @@ namespace debug { StackTrace::~StackTrace() { } -const void *const *StackTrace::Addresses(size_t* count) { +const void *const *StackTrace::Addresses(size_t* count) const { *count = count_; if (count_) return trace_; diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h index 8afc32c..acc7223 100644 --- a/base/debug/stack_trace.h +++ b/base/debug/stack_trace.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,7 @@ #include <iosfwd> +#include "base/base_api.h" #include "build/build_config.h" #if defined(OS_WIN) @@ -20,7 +21,7 @@ namespace debug { // A stacktrace can be helpful in debugging. For example, you can include a // stacktrace member in a object (probably around #ifndef NDEBUG) so that you // can later see where the given object was created from. -class StackTrace { +class BASE_API StackTrace { public: // Creates a stacktrace from the current location. StackTrace(); @@ -38,13 +39,13 @@ class StackTrace { // Gets an array of instruction pointer values. |*count| will be set to the // number of elements in the returned array. - const void* const* Addresses(size_t* count); + const void* const* Addresses(size_t* count) const; // Prints a backtrace to stderr - void PrintBacktrace(); + void PrintBacktrace() const; // Resolves backtrace to symbols and write to stream. - void OutputToStream(std::ostream* os); + void OutputToStream(std::ostream* os) const; private: // From http://msdn.microsoft.com/en-us/library/bb204633.aspx, diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc index 879110d..958cfdf 100644 --- a/base/debug/stack_trace_posix.cc +++ b/base/debug/stack_trace_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,6 +9,7 @@ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <sys/param.h> #include <sys/stat.h> #include <sys/sysctl.h> #include <sys/types.h> @@ -30,8 +31,8 @@ #include "base/basictypes.h" #include "base/eintr_wrapper.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/safe_strerror_posix.h" -#include "base/scoped_ptr.h" #include "base/string_piece.h" #include "base/stringprintf.h" @@ -105,7 +106,7 @@ void DemangleSymbols(std::string* text) { // names and attach these. Otherwise just use raw addresses. Returns true // if any symbol name is resolved. Returns false on error and *may* fill // in |error_message| if an error message is available. -bool GetBacktraceStrings(void **trace, int size, +bool GetBacktraceStrings(void *const *trace, int size, std::vector<std::string>* trace_strings, std::string* error_message) { #ifdef ANDROID @@ -168,11 +169,16 @@ StackTrace::StackTrace() { count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); } +<<<<<<< HEAD void StackTrace::PrintBacktrace() { #if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) #if defined(ANDROID) return; #else +======= +void StackTrace::PrintBacktrace() const { +#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +>>>>>>> chromium.org at r12.0.742.93 if (backtrace_symbols_fd == NULL) return; #endif // ANDROID @@ -185,11 +191,16 @@ void StackTrace::PrintBacktrace() { } } +<<<<<<< HEAD void StackTrace::OutputToStream(std::ostream* os) { #if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) #if defined(ANDROID) return; #else +======= +void StackTrace::OutputToStream(std::ostream* os) const { +#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +>>>>>>> chromium.org at r12.0.742.93 if (backtrace_symbols == NULL) return; #endif // ANDROID diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc index 510d35b..97376a2 100644 --- a/base/debug/stack_trace_win.cc +++ b/base/debug/stack_trace_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,7 +11,7 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "base/singleton.h" +#include "base/memory/singleton.h" #include "base/synchronization/lock.h" namespace base { @@ -174,11 +174,11 @@ StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) { } } -void StackTrace::PrintBacktrace() { +void StackTrace::PrintBacktrace() const { OutputToStream(&std::cerr); } -void StackTrace::OutputToStream(std::ostream* os) { +void StackTrace::OutputToStream(std::ostream* os) const { SymbolContext* context = SymbolContext::GetInstance(); DWORD error = context->init_error(); if (error != ERROR_SUCCESS) { diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h index e5c2cbd..6e818e1 100644 --- a/base/debug/trace_event.h +++ b/base/debug/trace_event.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -31,8 +31,8 @@ #include <string> -#include "base/scoped_ptr.h" -#include "base/singleton.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" #include "base/synchronization/lock.h" #include "base/time.h" #include "base/timer.h" diff --git a/base/debug/trace_event_win.cc b/base/debug/trace_event_win.cc index 005ff62..4929944 100644 --- a/base/debug/trace_event_win.cc +++ b/base/debug/trace_event_win.cc @@ -1,11 +1,11 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/debug/trace_event_win.h" #include "base/logging.h" -#include "base/singleton.h" +#include "base/memory/singleton.h" #include <initguid.h> // NOLINT namespace base { diff --git a/base/debug/trace_event_win.h b/base/debug/trace_event_win.h index a1c79ba..9049bdb 100644 --- a/base/debug/trace_event_win.h +++ b/base/debug/trace_event_win.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,8 @@ #pragma once #include <string> + +#include "base/base_api.h" #include "base/win/event_trace_provider.h" #define TRACE_EVENT_BEGIN(name, id, extra) \ @@ -40,7 +42,7 @@ namespace debug { // This EtwTraceProvider subclass implements ETW logging // for the macros above on Windows. -class TraceLog : public base::win::EtwTraceProvider { +class BASE_API TraceLog : public base::win::EtwTraceProvider { public: enum EventType { EVENT_BEGIN, @@ -117,13 +119,13 @@ class TraceLog : public base::win::EtwTraceProvider { }; // The ETW trace provider GUID. -extern const GUID kChromeTraceProviderName; +BASE_API extern const GUID kChromeTraceProviderName; // The ETW event class GUID for 32 bit events. -extern const GUID kTraceEventClass32; +BASE_API extern const GUID kTraceEventClass32; // The ETW event class GUID for 64 bit events. -extern const GUID kTraceEventClass64; +BASE_API extern const GUID kTraceEventClass64; // The ETW event types, IDs 0x00-0x09 are reserved, so start at 0x10. const base::win::EtwEventType kTraceEventTypeBegin = 0x10; diff --git a/base/environment.cc b/base/environment.cc index 9ccc078..0bfc68e 100644 --- a/base/environment.cc +++ b/base/environment.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,7 +13,7 @@ #include "base/string_util.h" #if defined(OS_WIN) -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/utf_string_conversions.h" #endif diff --git a/base/environment.h b/base/environment.h index 4c0691b..cf71724 100644 --- a/base/environment.h +++ b/base/environment.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,7 +8,8 @@ #include <string> -#include "base/basictypes.h" +#include "base/base_api.h" +#include "build/build_config.h" namespace base { @@ -20,7 +21,7 @@ extern const char kHome[]; } // namespace env_vars -class Environment { +class BASE_API Environment { public: virtual ~Environment(); diff --git a/base/environment_unittest.cc b/base/environment_unittest.cc index d1ce503..b6654c9 100644 --- a/base/environment_unittest.cc +++ b/base/environment_unittest.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/environment.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" diff --git a/base/event_recorder.cc b/base/event_recorder.cc index 1119b4f..b247380 100644 --- a/base/event_recorder.cc +++ b/base/event_recorder.cc @@ -1,9 +1,8 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" - +#include <stddef.h> #include <windows.h> #include <mmsystem.h> diff --git a/base/event_recorder.h b/base/event_recorder.h index e4d8907..1f7aa61 100644 --- a/base/event_recorder.h +++ b/base/event_recorder.h @@ -6,11 +6,15 @@ #define BASE_EVENT_RECORDER_H_ #pragma once +#include "base/base_api.h" +#include "base/basictypes.h" +#include "build/build_config.h" + #if defined(OS_WIN) -#include <windows.h> #include <stdio.h> +#include <string.h> +#include <windows.h> #endif -#include "base/basictypes.h" class FilePath; @@ -29,7 +33,7 @@ namespace base { // Why? Imagine if the product had a "record a macro" feature. // You might be recording globally, while recording or playing back // a macro. I don't think two playbacks make sense. -class EventRecorder { +class BASE_API EventRecorder { public: // Get the singleton EventRecorder. // We can only handle one recorder/player at a time. diff --git a/base/file_descriptor_shuffle.cc b/base/file_descriptor_shuffle.cc index 2bb156b..7ad9787 100644 --- a/base/file_descriptor_shuffle.cc +++ b/base/file_descriptor_shuffle.cc @@ -1,11 +1,12 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/file_descriptor_shuffle.h" -#include <errno.h> #include <unistd.h> +#include <stddef.h> +#include <ostream> #include "base/eintr_wrapper.h" #include "base/logging.h" diff --git a/base/file_path.cc b/base/file_path.cc index 29ec7a8..0d0b40b 100644 --- a/base/file_path.cc +++ b/base/file_path.cc @@ -1,17 +1,13 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <algorithm> - #include "base/file_path.h" -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_MACOSX) -#include <CoreFoundation/CoreFoundation.h> -#endif +#include <string.h> +#include <algorithm> +#include "base/basictypes.h" #include "base/logging.h" #include "base/pickle.h" @@ -27,6 +23,12 @@ #include "base/third_party/icu/icu_utf.h" #endif +#if defined(OS_WIN) +#include <windows.h> +#elif defined(OS_MACOSX) +#include <CoreFoundation/CoreFoundation.h> +#endif + #if defined(FILE_PATH_USES_WIN_SEPARATORS) const FilePath::CharType FilePath::kSeparators[] = FILE_PATH_LITERAL("\\/"); #else // FILE_PATH_USES_WIN_SEPARATORS @@ -63,8 +65,8 @@ StringType::size_type FindDriveLetter(const StringType& path) { } #if defined(FILE_PATH_USES_DRIVE_LETTERS) -bool EqualDriveLetterCaseInsensitive(const StringType a, - const StringType b) { +bool EqualDriveLetterCaseInsensitive(const StringType& a, + const StringType& b) { size_t a_letter_pos = FindDriveLetter(a); size_t b_letter_pos = FindDriveLetter(b); @@ -532,9 +534,6 @@ std::string FilePath::MaybeAsASCII() const { FilePath FilePath::FromWStringHack(const std::wstring& wstring) { return FilePath(base::SysWideToNativeMB(wstring)); } -std::wstring FilePath::ToWStringHack() const { - return base::SysNativeMBToWide(path_); -} #elif defined(OS_WIN) string16 FilePath::LossyDisplayName() const { return path_; @@ -550,9 +549,6 @@ std::string FilePath::MaybeAsASCII() const { FilePath FilePath::FromWStringHack(const std::wstring& wstring) { return FilePath(wstring); } -std::wstring FilePath::ToWStringHack() const { - return path_; -} #endif // static. diff --git a/base/file_path.h b/base/file_path.h index 1afa7a6..fd9260c 100644 --- a/base/file_path.h +++ b/base/file_path.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -100,13 +100,16 @@ #define BASE_FILE_PATH_H_ #pragma once +#include <stddef.h> #include <string> #include <vector> -#include "base/basictypes.h" +#include "base/base_api.h" #include "base/compiler_specific.h" #include "base/hash_tables.h" +#include "base/string16.h" #include "base/string_piece.h" // For implicit conversions. +#include "build/build_config.h" // Windows-style drive letter support and pathname separator characters can be // enabled and disabled independently, to aid testing. These #defines are @@ -121,7 +124,7 @@ class Pickle; // An abstraction to isolate users from the differences between native // pathnames on different platforms. -class FilePath { +class BASE_API FilePath { public: #if defined(OS_POSIX) // On most platforms, native pathnames are char arrays, and the encoding @@ -289,9 +292,9 @@ class FilePath { std::string MaybeAsASCII() const; // Older Chromium code assumes that paths are always wstrings. - // These functions convert wstrings to/from FilePaths, and are + // This function converts wstrings to FilePaths, and is // useful to smooth porting that old code to the FilePath API. - // They have "Hack" in their names so people feel bad about using them. + // It has "Hack" its name so people feel bad about using it. // http://code.google.com/p/chromium/issues/detail?id=24672 // // If you are trying to be a good citizen and remove these, ask yourself: @@ -305,7 +308,6 @@ class FilePath { // LossyDisplayName() function, but keep in mind that you can't // ever use the result of that again as a path. static FilePath FromWStringHack(const std::wstring& wstring); - std::wstring ToWStringHack() const; // Static helper method to write a StringType to a pickle. static void WriteStringTypeToPickle(Pickle* pickle, @@ -386,7 +388,7 @@ namespace __gnu_cxx { template<> struct hash<FilePath> { - std::size_t operator()(const FilePath& f) const { + size_t operator()(const FilePath& f) const { return hash<FilePath::StringType>()(f.value()); } }; diff --git a/base/file_util.h b/base/file_util.h index 108c998..6fe9a3d 100644 --- a/base/file_util.h +++ b/base/file_util.h @@ -26,10 +26,11 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/file_path.h" +#include "base/memory/scoped_ptr.h" #include "base/platform_file.h" -#include "base/scoped_ptr.h" #include "base/string16.h" #if defined(OS_POSIX) @@ -48,19 +49,19 @@ namespace file_util { // Functions that operate purely on a path string w/o touching the filesystem: // Returns true if the given path ends with a path separator character. -bool EndsWithSeparator(const FilePath& path); +BASE_API bool EndsWithSeparator(const FilePath& path); // Makes sure that |path| ends with a separator IFF path is a directory that // exists. Returns true if |path| is an existing directory, false otherwise. -bool EnsureEndsWithSeparator(FilePath* path); +BASE_API bool EnsureEndsWithSeparator(FilePath* path); // Convert provided relative path into an absolute path. Returns false on // error. On POSIX, this function fails if the path does not exist. -bool AbsolutePath(FilePath* path); +BASE_API bool AbsolutePath(FilePath* path); // Returns true if |parent| contains |child|. Both paths are converted to // absolute paths before doing the comparison. -bool ContainsPath(const FilePath& parent, const FilePath& child); +BASE_API bool ContainsPath(const FilePath& parent, const FilePath& child); //----------------------------------------------------------------------------- // Functions that involve filesystem access or modification: @@ -73,15 +74,15 @@ bool ContainsPath(const FilePath& parent, const FilePath& child); // timestmap of file creation time. If you need to avoid such // mis-detection perfectly, you should wait one second before // obtaining |file_time|. -int CountFilesCreatedAfter(const FilePath& path, - const base::Time& file_time); +BASE_API int CountFilesCreatedAfter(const FilePath& path, + const base::Time& file_time); // Returns the total number of bytes used by all the files under |root_path|. // If the path does not exist the function returns 0. // // This function is implemented using the FileEnumerator class so it is not // particularly speedy in any platform. -int64 ComputeDirectorySize(const FilePath& root_path); +BASE_API int64 ComputeDirectorySize(const FilePath& root_path); // Returns the total number of bytes used by all files matching the provided // |pattern|, on this |directory| (without recursion). If the path does not @@ -89,8 +90,8 @@ int64 ComputeDirectorySize(const FilePath& root_path); // // This function is implemented using the FileEnumerator class so it is not // particularly speedy in any platform. -int64 ComputeFilesSize(const FilePath& directory, - const FilePath::StringType& pattern); +BASE_API int64 ComputeFilesSize(const FilePath& directory, + const FilePath::StringType& pattern); // Deletes the given path, whether it's a file or a directory. // If it's a directory, it's perfectly happy to delete all of the @@ -100,7 +101,7 @@ int64 ComputeFilesSize(const FilePath& directory, // // WARNING: USING THIS WITH recursive==true IS EQUIVALENT // TO "rm -rf", SO USE WITH CAUTION. -bool Delete(const FilePath& path, bool recursive); +BASE_API bool Delete(const FilePath& path, bool recursive); #if defined(OS_WIN) // Schedules to delete the given path, whether it's a file or a directory, until @@ -108,24 +109,24 @@ bool Delete(const FilePath& path, bool recursive); // Note: // 1) The file/directory to be deleted should exist in a temp folder. // 2) The directory to be deleted must be empty. -bool DeleteAfterReboot(const FilePath& path); +BASE_API bool DeleteAfterReboot(const FilePath& path); #endif // Moves the given path, whether it's a file or a directory. // If a simple rename is not possible, such as in the case where the paths are // on different volumes, this will attempt to copy and delete. Returns // true for success. -bool Move(const FilePath& from_path, const FilePath& to_path); +BASE_API bool Move(const FilePath& from_path, const FilePath& to_path); // Renames file |from_path| to |to_path|. Both paths must be on the same // volume, or the function will fail. Destination file will be created // if it doesn't exist. Prefer this function over Move when dealing with // temporary files. On Windows it preserves attributes of the target file. // Returns true on success. -bool ReplaceFile(const FilePath& from_path, const FilePath& to_path); +BASE_API bool ReplaceFile(const FilePath& from_path, const FilePath& to_path); // Copies a single file. Use CopyDirectory to copy directories. -bool CopyFile(const FilePath& from_path, const FilePath& to_path); +BASE_API bool CopyFile(const FilePath& from_path, const FilePath& to_path); // Copies the given path, and optionally all subdirectories and their contents // as well. @@ -134,45 +135,46 @@ bool CopyFile(const FilePath& from_path, const FilePath& to_path); // Don't use wildcards on the names, it may stop working without notice. // // If you only need to copy a file use CopyFile, it's faster. -bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, - bool recursive); +BASE_API bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, + bool recursive); // Returns true if the given path exists on the local filesystem, // false otherwise. -bool PathExists(const FilePath& path); +BASE_API bool PathExists(const FilePath& path); // Returns true if the given path is writable by the user, false otherwise. -bool PathIsWritable(const FilePath& path); +BASE_API bool PathIsWritable(const FilePath& path); // Returns true if the given path exists and is a directory, false otherwise. -bool DirectoryExists(const FilePath& path); +BASE_API bool DirectoryExists(const FilePath& path); #if defined(OS_WIN) // Gets the creation time of the given file (expressed in the local timezone), // and returns it via the creation_time parameter. Returns true if successful, // false otherwise. -bool GetFileCreationLocalTime(const std::wstring& filename, - LPSYSTEMTIME creation_time); +BASE_API bool GetFileCreationLocalTime(const std::wstring& filename, + LPSYSTEMTIME creation_time); // Same as above, but takes a previously-opened file handle instead of a name. -bool GetFileCreationLocalTimeFromHandle(HANDLE file_handle, - LPSYSTEMTIME creation_time); +BASE_API bool GetFileCreationLocalTimeFromHandle(HANDLE file_handle, + LPSYSTEMTIME creation_time); #endif // defined(OS_WIN) // Returns true if the contents of the two files given are equal, false // otherwise. If either file can't be read, returns false. -bool ContentsEqual(const FilePath& filename1, - const FilePath& filename2); +BASE_API bool ContentsEqual(const FilePath& filename1, + const FilePath& filename2); // Returns true if the contents of the two text files given are equal, false // otherwise. This routine treats "\r\n" and "\n" as equivalent. -bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2); +BASE_API bool TextContentsEqual(const FilePath& filename1, + const FilePath& filename2); // Read the file at |path| into |contents|, returning true on success. // |contents| may be NULL, in which case this function is useful for its // side effect of priming the disk cache. // Useful for unit tests. -bool ReadFileToString(const FilePath& path, std::string* contents); +BASE_API bool ReadFileToString(const FilePath& path, std::string* contents); #if defined(OS_POSIX) // Read exactly |bytes| bytes from file descriptor |fd|, storing the result @@ -194,7 +196,7 @@ bool ReadSymbolicLink(const FilePath& symlink, FilePath* target); // This methods tries to resolve a shortcut .LNK file. If the |path| is valid // returns true and puts the target into the |path|, otherwise returns // false leaving the path as it is. -bool ResolveShortcut(FilePath* path); +BASE_API bool ResolveShortcut(FilePath* path); // Create a Windows shortcut (.LNK file) // This method creates a shortcut link using the information given. Ensure @@ -205,10 +207,14 @@ bool ResolveShortcut(FilePath* path); // The 'icon' can specify a dll or exe in which case the icon index is the // resource id. 'app_id' is the app model id for the shortcut on Win7. // Note that if the shortcut exists it will overwrite it. -bool CreateShortcutLink(const wchar_t *source, const wchar_t *destination, - const wchar_t *working_dir, const wchar_t *arguments, - const wchar_t *description, const wchar_t *icon, - int icon_index, const wchar_t* app_id); +BASE_API bool CreateShortcutLink(const wchar_t *source, + const wchar_t *destination, + const wchar_t *working_dir, + const wchar_t *arguments, + const wchar_t *description, + const wchar_t *icon, + int icon_index, + const wchar_t* app_id); // Update a Windows shortcut (.LNK file). This method assumes the shortcut // link already exists (otherwise false is returned). Ensure you have @@ -217,86 +223,92 @@ bool CreateShortcutLink(const wchar_t *source, const wchar_t *destination, // is NULL no changes are made to the shortcut). 'destination' is the link // file to be updated. 'app_id' is the app model id for the shortcut on Win7. // For best results pass the filename with the .lnk extension. -bool UpdateShortcutLink(const wchar_t *source, const wchar_t *destination, - const wchar_t *working_dir, const wchar_t *arguments, - const wchar_t *description, const wchar_t *icon, - int icon_index, const wchar_t* app_id); +BASE_API bool UpdateShortcutLink(const wchar_t *source, + const wchar_t *destination, + const wchar_t *working_dir, + const wchar_t *arguments, + const wchar_t *description, + const wchar_t *icon, + int icon_index, + const wchar_t* app_id); // Pins a shortcut to the Windows 7 taskbar. The shortcut file must already // exist and be a shortcut that points to an executable. -bool TaskbarPinShortcutLink(const wchar_t* shortcut); +BASE_API bool TaskbarPinShortcutLink(const wchar_t* shortcut); // Unpins a shortcut from the Windows 7 taskbar. The shortcut must exist and // already be pinned to the taskbar. -bool TaskbarUnpinShortcutLink(const wchar_t* shortcut); +BASE_API bool TaskbarUnpinShortcutLink(const wchar_t* shortcut); // Copy from_path to to_path recursively and then delete from_path recursively. // Returns true if all operations succeed. // This function simulates Move(), but unlike Move() it works across volumes. // This fuction is not transactional. -bool CopyAndDeleteDirectory(const FilePath& from_path, - const FilePath& to_path); +BASE_API bool CopyAndDeleteDirectory(const FilePath& from_path, + const FilePath& to_path); #endif // defined(OS_WIN) // Return true if the given directory is empty -bool IsDirectoryEmpty(const FilePath& dir_path); +BASE_API bool IsDirectoryEmpty(const FilePath& dir_path); // Get the temporary directory provided by the system. // WARNING: DON'T USE THIS. If you want to create a temporary file, use one of // the functions below. -bool GetTempDir(FilePath* path); +BASE_API bool GetTempDir(FilePath* path); // Get a temporary directory for shared memory files. // Only useful on POSIX; redirects to GetTempDir() on Windows. -bool GetShmemTempDir(FilePath* path); +BASE_API bool GetShmemTempDir(FilePath* path); // Get the home directory. This is more complicated than just getenv("HOME") // as it knows to fall back on getpwent() etc. -FilePath GetHomeDir(); +BASE_API FilePath GetHomeDir(); // Creates a temporary file. The full path is placed in |path|, and the // function returns true if was successful in creating the file. The file will // be empty and all handles closed after this function returns. -bool CreateTemporaryFile(FilePath* path); +BASE_API bool CreateTemporaryFile(FilePath* path); // Same as CreateTemporaryFile but the file is created in |dir|. -bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file); +BASE_API bool CreateTemporaryFileInDir(const FilePath& dir, + FilePath* temp_file); // Create and open a temporary file. File is opened for read/write. // The full path is placed in |path|. // Returns a handle to the opened file or NULL if an error occured. -FILE* CreateAndOpenTemporaryFile(FilePath* path); +BASE_API FILE* CreateAndOpenTemporaryFile(FilePath* path); // Like above but for shmem files. Only useful for POSIX. -FILE* CreateAndOpenTemporaryShmemFile(FilePath* path); +BASE_API FILE* CreateAndOpenTemporaryShmemFile(FilePath* path); // Similar to CreateAndOpenTemporaryFile, but the file is created in |dir|. -FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path); +BASE_API FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, + FilePath* path); // Create a new directory. If prefix is provided, the new directory name is in // the format of prefixyyyy. // NOTE: prefix is ignored in the POSIX implementation. // If success, return true and output the full path of the directory created. -bool CreateNewTempDirectory(const FilePath::StringType& prefix, - FilePath* new_temp_path); +BASE_API bool CreateNewTempDirectory(const FilePath::StringType& prefix, + FilePath* new_temp_path); // Create a directory within another directory. // Extra characters will be appended to |prefix| to ensure that the // new directory does not have the same name as an existing directory. -bool CreateTemporaryDirInDir(const FilePath& base_dir, - const FilePath::StringType& prefix, - FilePath* new_dir); +BASE_API bool CreateTemporaryDirInDir(const FilePath& base_dir, + const FilePath::StringType& prefix, + FilePath* new_dir); // Creates a directory, as well as creating any parent directories, if they // don't exist. Returns 'true' on successful creation, or if the directory // already exists. The directory is only readable by the current user. -bool CreateDirectory(const FilePath& full_path); +BASE_API bool CreateDirectory(const FilePath& full_path); // Returns the file size. Returns true on success. -bool GetFileSize(const FilePath& file_path, int64* file_size); +BASE_API bool GetFileSize(const FilePath& file_path, int64* file_size); // Returns true if the given path's base name is ".". -bool IsDot(const FilePath& path); +BASE_API bool IsDot(const FilePath& path); // Returns true if the given path's base name is "..". -bool IsDotDot(const FilePath& path); +BASE_API bool IsDotDot(const FilePath& path); // Sets |real_path| to |path| with symbolic links and junctions expanded. // On windows, make sure the path starts with a lettered drive. @@ -304,27 +316,29 @@ bool IsDotDot(const FilePath& path); // a directory or to a nonexistent path. On windows, this function will // fail if |path| is a junction or symlink that points to an empty file, // or if |real_path| would be longer than MAX_PATH characters. -bool NormalizeFilePath(const FilePath& path, FilePath* real_path); +BASE_API bool NormalizeFilePath(const FilePath& path, FilePath* real_path); #if defined(OS_WIN) // Given an existing file in |path|, it returns in |real_path| the path // in the native NT format, of the form "\Device\HarddiskVolumeXX\..". // Returns false it it fails. Empty files cannot be resolved with this // function. -bool NormalizeToNativeFilePath(const FilePath& path, FilePath* nt_path); +BASE_API bool NormalizeToNativeFilePath(const FilePath& path, + FilePath* nt_path); #endif // Returns information about the given file path. -bool GetFileInfo(const FilePath& file_path, base::PlatformFileInfo* info); +BASE_API bool GetFileInfo(const FilePath& file_path, + base::PlatformFileInfo* info); // Sets the time of the last access and the time of the last modification. -bool TouchFile(const FilePath& path, - const base::Time& last_accessed, - const base::Time& last_modified); +BASE_API bool TouchFile(const FilePath& path, + const base::Time& last_accessed, + const base::Time& last_modified); // Set the time of the last modification. Useful for unit tests. -bool SetLastModifiedTime(const FilePath& path, - const base::Time& last_modified); +BASE_API bool SetLastModifiedTime(const FilePath& path, + const base::Time& last_modified); #if defined(OS_POSIX) // Store inode number of |path| in |inode|. Return true on success. @@ -332,32 +346,32 @@ bool GetInode(const FilePath& path, ino_t* inode); #endif // Wrapper for fopen-like calls. Returns non-NULL FILE* on success. -FILE* OpenFile(const FilePath& filename, const char* mode); +BASE_API FILE* OpenFile(const FilePath& filename, const char* mode); // Closes file opened by OpenFile. Returns true on success. -bool CloseFile(FILE* file); +BASE_API bool CloseFile(FILE* file); // Truncates an open file to end at the location of the current file pointer. // This is a cross-platform analog to Windows' SetEndOfFile() function. -bool TruncateFile(FILE* file); +BASE_API bool TruncateFile(FILE* file); // Reads the given number of bytes from the file into the buffer. Returns // the number of read bytes, or -1 on error. -int ReadFile(const FilePath& filename, char* data, int size); +BASE_API int ReadFile(const FilePath& filename, char* data, int size); // Writes the given buffer into the file, overwriting any data that was // previously there. Returns the number of bytes written, or -1 on error. -int WriteFile(const FilePath& filename, const char* data, int size); +BASE_API int WriteFile(const FilePath& filename, const char* data, int size); #if defined(OS_POSIX) // Append the data to |fd|. Does not close |fd| when done. int WriteFileDescriptor(const int fd, const char* data, int size); #endif // Gets the current working directory for the process. -bool GetCurrentDirectory(FilePath* path); +BASE_API bool GetCurrentDirectory(FilePath* path); // Sets the current working directory for the process. -bool SetCurrentDirectory(const FilePath& path); +BASE_API bool SetCurrentDirectory(const FilePath& path); // A class to handle auto-closing of FILE*'s. class ScopedFILEClose { @@ -391,7 +405,7 @@ typedef scoped_ptr_malloc<int, ScopedFDClose> ScopedFD; // // DO NOT USE FROM THE MAIN THREAD of your application unless it is a test // program where latency does not matter. This class is blocking. -class FileEnumerator { +class BASE_API FileEnumerator { public: #if defined(OS_WIN) typedef WIN32_FIND_DATA FindInfo; @@ -490,7 +504,7 @@ class FileEnumerator { DISALLOW_COPY_AND_ASSIGN(FileEnumerator); }; -class MemoryMappedFile { +class BASE_API MemoryMappedFile { public: // The default constructor sets all members to invalid/null values. MemoryMappedFile(); @@ -545,13 +559,14 @@ class MemoryMappedFile { // Renames a file using the SHFileOperation API to ensure that the target file // gets the correct default security descriptor in the new path. -bool RenameFileAndResetSecurityDescriptor( +BASE_API bool RenameFileAndResetSecurityDescriptor( const FilePath& source_file_path, const FilePath& target_file_path); // Returns whether the file has been modified since a particular date. -bool HasFileBeenModifiedSince(const FileEnumerator::FindInfo& find_info, - const base::Time& cutoff_time); +BASE_API bool HasFileBeenModifiedSince( + const FileEnumerator::FindInfo& find_info, + const base::Time& cutoff_time); #ifdef UNIT_TEST @@ -611,8 +626,8 @@ inline bool MakeFileUnreadable(const FilePath& path) { // is passed in. If it is 0 then the whole file is paged in. The step size // which indicates the number of bytes to skip after every page touched is // also passed in. -bool PreReadImage(const wchar_t* file_path, size_t size_to_read, - size_t step_size); +bool BASE_API PreReadImage(const wchar_t* file_path, size_t size_to_read, + size_t step_size); #endif // OS_WIN #if defined(OS_LINUX) @@ -625,6 +640,7 @@ enum FileSystemType { FILE_SYSTEM_SMB, FILE_SYSTEM_CODA, FILE_SYSTEM_MEMORY, // in-memory file system + FILE_SYSTEM_CGROUP, // cgroup control. FILE_SYSTEM_OTHER, // any other value. FILE_SYSTEM_TYPE_COUNT }; diff --git a/base/file_util_deprecated.h b/base/file_util_deprecated.h index dac4b45..d24e54d 100644 --- a/base/file_util_deprecated.h +++ b/base/file_util_deprecated.h @@ -14,6 +14,7 @@ #define BASE_FILE_UTIL_DEPRECATED_H_ #pragma once +#include "base/base_api.h" #include "build/build_config.h" // We've successfully deprecated all of these functions on non-Windows @@ -24,22 +25,24 @@ namespace file_util { // Use the FilePath versions instead. -FILE* OpenFile(const std::string& filename, const char* mode); -FILE* OpenFile(const std::wstring& filename, const char* mode); +BASE_API FILE* OpenFile(const std::string& filename, const char* mode); +BASE_API FILE* OpenFile(const std::wstring& filename, const char* mode); // Appends new_ending to path, adding a separator between the two if necessary. -void AppendToPath(std::wstring* path, const std::wstring& new_ending); +BASE_API void AppendToPath(std::wstring* path, const std::wstring& new_ending); // Use FilePath::Extension instead. -FilePath::StringType GetFileExtensionFromPath(const FilePath& path); -std::wstring GetFileExtensionFromPath(const std::wstring& path); +BASE_API FilePath::StringType GetFileExtensionFromPath(const FilePath& path); +BASE_API std::wstring GetFileExtensionFromPath(const 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, - bool recursive); -int ReadFile(const std::wstring& filename, char* data, int size); -int WriteFile(const std::wstring& filename, const char* data, int size); +BASE_API bool Delete(const std::wstring& path, bool recursive); +BASE_API bool CopyDirectory(const std::wstring& from_path, + const std::wstring& to_path, + bool recursive); +BASE_API int ReadFile(const std::wstring& filename, char* data, int size); +BASE_API int WriteFile(const std::wstring& filename, + const char* data, int size); } diff --git a/base/file_util_linux.cc b/base/file_util_linux.cc index dd0c820..f7d4f6e 100644 --- a/base/file_util_linux.cc +++ b/base/file_util_linux.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -50,6 +50,9 @@ bool GetFileSystemType(const FilePath& path, FileSystemType* type) { case 0x01021994: // tmpfs *type = FILE_SYSTEM_MEMORY; break; + case 0x27e0eb: // CGROUP + *type = FILE_SYSTEM_CGROUP; + break; default: *type = FILE_SYSTEM_OTHER; } diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc index 9a2d90a..34e0938 100644 --- a/base/file_util_posix.cc +++ b/base/file_util_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -34,8 +34,8 @@ #include "base/eintr_wrapper.h" #include "base/file_path.h" #include "base/logging.h" -#include "base/scoped_ptr.h" -#include "base/singleton.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "base/threading/thread_restrictions.h" @@ -407,7 +407,7 @@ int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) { // this should be OK since mkstemp just replaces characters in place char* buffer = const_cast<char*>(tmpdir_string.c_str()); - return mkstemp(buffer); + return HANDLE_EINTR(mkstemp(buffer)); } bool CreateTemporaryFile(FilePath* path) { @@ -418,7 +418,7 @@ bool CreateTemporaryFile(FilePath* path) { int fd = CreateAndOpenFdForTemporaryFile(directory, path); if (fd < 0) return false; - close(fd); + ignore_result(HANDLE_EINTR(close(fd))); return true; } @@ -435,13 +435,16 @@ FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) { if (fd < 0) return NULL; - return fdopen(fd, "a+"); + FILE* file = fdopen(fd, "a+"); + if (!file) + ignore_result(HANDLE_EINTR(close(fd))); + return file; } bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). int fd = CreateAndOpenFdForTemporaryFile(dir, temp_file); - return ((fd >= 0) && !close(fd)); + return ((fd >= 0) && !HANDLE_EINTR(close(fd))); } static bool CreateTemporaryDirInDirImpl(const FilePath& base_dir, @@ -541,12 +544,16 @@ FILE* OpenFile(const std::string& filename, const char* mode) { FILE* OpenFile(const FilePath& filename, const char* mode) { base::ThreadRestrictions::AssertIOAllowed(); - return fopen(filename.value().c_str(), mode); + FILE* result = NULL; + do { + result = fopen(filename.value().c_str(), mode); + } while (!result && errno == EINTR); + return result; } int ReadFile(const FilePath& filename, char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - int fd = open(filename.value().c_str(), O_RDONLY); + int fd = HANDLE_EINTR(open(filename.value().c_str(), O_RDONLY)); if (fd < 0) return -1; @@ -558,7 +565,7 @@ int ReadFile(const FilePath& filename, char* data, int size) { int WriteFile(const FilePath& filename, const char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - int fd = creat(filename.value().c_str(), 0666); + int fd = HANDLE_EINTR(creat(filename.value().c_str(), 0666)); if (fd < 0) return -1; @@ -776,7 +783,7 @@ void MemoryMappedFile::CloseHandles() { if (data_ != NULL) munmap(data_, length_); if (file_ != base::kInvalidPlatformFileValue) - close(file_); + ignore_result(HANDLE_EINTR(close(file_))); data_ = NULL; length_ = 0; @@ -842,13 +849,13 @@ FilePath GetHomeDir() { bool CopyFile(const FilePath& from_path, const FilePath& to_path) { base::ThreadRestrictions::AssertIOAllowed(); - int infile = open(from_path.value().c_str(), O_RDONLY); + int infile = HANDLE_EINTR(open(from_path.value().c_str(), O_RDONLY)); if (infile < 0) return false; - int outfile = creat(to_path.value().c_str(), 0666); + int outfile = HANDLE_EINTR(creat(to_path.value().c_str(), 0666)); if (outfile < 0) { - close(infile); + ignore_result(HANDLE_EINTR(close(infile))); return false; } diff --git a/base/file_util_proxy.cc b/base/file_util_proxy.cc index d357e98..1d5b9cc 100644 --- a/base/file_util_proxy.cc +++ b/base/file_util_proxy.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -570,7 +570,8 @@ class RelayWrite : public MessageLoopRelay { offset_(offset), buffer_(new char[bytes_to_write]), bytes_to_write_(bytes_to_write), - callback_(callback) { + callback_(callback), + bytes_written_(0) { memcpy(buffer_.get(), buffer, bytes_to_write); } diff --git a/base/file_util_proxy.h b/base/file_util_proxy.h index f2368cc..08df57b 100644 --- a/base/file_util_proxy.h +++ b/base/file_util_proxy.h @@ -7,11 +7,12 @@ #include <vector> +#include "base/base_api.h" #include "base/callback.h" #include "base/file_path.h" #include "base/file_util.h" +#include "base/memory/ref_counted.h" #include "base/platform_file.h" -#include "base/ref_counted.h" #include "base/tracked_objects.h" namespace base { @@ -20,7 +21,7 @@ class MessageLoopProxy; class Time; // This class provides asynchronous access to common file routines. -class FileUtilProxy { +class BASE_API FileUtilProxy { public: // Holds metadata for file or directory entry. Used by ReadDirectoryCallback. struct Entry { diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc index ea29df5..733f9f1 100644 --- a/base/file_util_unittest.cc +++ b/base/file_util_unittest.cc @@ -18,8 +18,8 @@ #include "base/base_paths.h" #include "base/file_path.h" #include "base/file_util.h" +#include "base/memory/scoped_temp_dir.h" #include "base/path_service.h" -#include "base/scoped_temp_dir.h" #include "base/threading/platform_thread.h" #include "base/time.h" #include "base/utf_string_conversions.h" @@ -162,7 +162,7 @@ class FindResultCollector { // Simple function to dump some text into a new file. void CreateTextFile(const FilePath& filename, const std::wstring& contents) { - std::ofstream file; + std::wofstream file; file.open(filename.value().c_str()); ASSERT_TRUE(file.is_open()); file << contents; @@ -175,7 +175,7 @@ std::wstring ReadTextFile(const FilePath& filename) { std::wifstream file; file.open(filename.value().c_str()); EXPECT_TRUE(file.is_open()); - file.getline(contents, 64); + file.getline(contents, arraysize(contents)); file.close(); return std::wstring(contents); } diff --git a/base/file_util_win.cc b/base/file_util_win.cc index 2c26a16..3689614 100644 --- a/base/file_util_win.cc +++ b/base/file_util_win.cc @@ -55,7 +55,7 @@ bool DevicePathToDriveLetterPath(const FilePath& device_path, // For each string in the drive mapping, get the junction that links // to it. If that junction is a prefix of |device_path|, then we // know that |drive| is the real path prefix. - while(*drive_map_ptr) { + while (*drive_map_ptr) { drive[0] = drive_map_ptr[0]; // Copy the drive letter. if (QueryDosDevice(drive, device_name, MAX_PATH) && @@ -66,7 +66,7 @@ bool DevicePathToDriveLetterPath(const FilePath& device_path, } // Move to the next drive letter string, which starts one // increment after the '\0' that terminates the current string. - while(*drive_map_ptr++); + while (*drive_map_ptr++); } // No drive matched. The path does not start with a device junction @@ -104,7 +104,7 @@ int CountFilesCreatedAfter(const FilePath& path, (wcscmp(find_file_data.cFileName, L".") == 0)) continue; - long result = CompareFileTime(&find_file_data.ftCreationTime, + long result = CompareFileTime(&find_file_data.ftCreationTime, // NOLINT &comparison_filetime); // File was created after or on comparison time if ((result == 1) || (result == 0)) @@ -187,13 +187,26 @@ bool Move(const FilePath& from_path, const FilePath& to_path) { if (MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) != 0) return true; + + // Keep the last error value from MoveFileEx around in case the below + // fails. + bool ret = false; + DWORD last_error = ::GetLastError(); + if (DirectoryExists(from_path)) { // MoveFileEx fails if moving directory across volumes. We will simulate // the move by using Copy and Delete. Ideally we could check whether // from_path and to_path are indeed in different volumes. - return CopyAndDeleteDirectory(from_path, to_path); + ret = CopyAndDeleteDirectory(from_path, to_path); } - return false; + + if (!ret) { + // Leave a clue about what went wrong so that it can be (at least) picked + // up by a PLOG entry. + ::SetLastError(last_error); + } + + return ret; } bool ReplaceFile(const FilePath& from_path, const FilePath& to_path) { @@ -442,7 +455,6 @@ bool CreateShortcutLink(const wchar_t *source, const wchar_t *destination, return SUCCEEDED(result); } - bool UpdateShortcutLink(const wchar_t *source, const wchar_t *destination, const wchar_t *working_dir, const wchar_t *arguments, const wchar_t *description, const wchar_t *icon, @@ -491,6 +503,16 @@ bool UpdateShortcutLink(const wchar_t *source, const wchar_t *destination, } HRESULT result = i_persist_file->Save(destination, TRUE); + + i_persist_file.Release(); + i_shell_link.Release(); + + // If we successfully updated the icon, notify the shell that we have done so. + if (SUCCEEDED(result)) { + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, + NULL, NULL); + } + return SUCCEEDED(result); } @@ -921,8 +943,9 @@ FilePath FileEnumerator::Next() { } if (file_type_ & FileEnumerator::DIRECTORIES) return cur_file; - } else if (file_type_ & FileEnumerator::FILES) + } else if (file_type_ & FileEnumerator::FILES) { return cur_file; + } } return FilePath(); @@ -972,10 +995,8 @@ bool MemoryMappedFile::MapFileToMemoryInternalEx(int flags) { if (length_ == INVALID_FILE_SIZE) return false; - // length_ value comes from GetFileSize() above. GetFileSize() returns DWORD, - // therefore the cast here is safe. file_mapping_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY | flags, - 0, static_cast<DWORD>(length_), NULL); + 0, 0, NULL); if (!file_mapping_) { // According to msdn, system error codes are only reserved up to 15999. // http://msdn.microsoft.com/en-us/library/ms681381(v=VS.85).aspx. @@ -985,7 +1006,7 @@ bool MemoryMappedFile::MapFileToMemoryInternalEx(int flags) { } data_ = static_cast<uint8*>( - ::MapViewOfFile(file_mapping_, FILE_MAP_READ, 0, 0, length_)); + ::MapViewOfFile(file_mapping_, FILE_MAP_READ, 0, 0, 0)); if (!data_) { UMA_HISTOGRAM_ENUMERATION("MemoryMappedFile.MapViewOfFile", logging::GetLastSystemErrorCode(), 16000); @@ -1009,7 +1030,7 @@ void MemoryMappedFile::CloseHandles() { bool HasFileBeenModifiedSince(const FileEnumerator::FindInfo& find_info, const base::Time& cutoff_time) { base::ThreadRestrictions::AssertIOAllowed(); - long result = CompareFileTime(&find_info.ftLastWriteTime, + long result = CompareFileTime(&find_info.ftLastWriteTime, // NOLINT &cutoff_time.ToFileTime()); return result == 1 || result == 0; } @@ -1052,7 +1073,7 @@ bool NormalizeToNativeFilePath(const FilePath& path, FilePath* nt_path) { NULL, PAGE_READONLY, 0, - 1, // Just one byte. No need to look at the data. + 1, // Just one byte. No need to look at the data. NULL)); if (!file_map_handle) return false; diff --git a/base/file_version_info.h b/base/file_version_info.h index 481e88d..dca4148 100644 --- a/base/file_version_info.h +++ b/base/file_version_info.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,11 +6,11 @@ #define BASE_FILE_VERSION_INFO_H__ #pragma once -#include "build/build_config.h" - #include <string> +#include "base/base_api.h" #include "base/string16.h" +#include "build/build_config.h" class FilePath; @@ -24,7 +24,7 @@ class FilePath; // version returns values from the Info.plist as appropriate. TODO(avi): make // this a less-obvious Windows-ism. -class FileVersionInfo { +class BASE_API FileVersionInfo { public: virtual ~FileVersionInfo() {} #if defined(OS_WIN) || defined(OS_MACOSX) diff --git a/base/file_version_info_mac.h b/base/file_version_info_mac.h index d8cb1a6..7c0184a 100644 --- a/base/file_version_info_mac.h +++ b/base/file_version_info_mac.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,7 @@ #include <string> #include "base/file_version_info.h" -#include "base/scoped_nsobject.h" +#include "base/memory/scoped_nsobject.h" #ifdef __OBJC__ @class NSBundle; diff --git a/base/file_version_info_mac.mm b/base/file_version_info_mac.mm index bcfd854..293d904 100644 --- a/base/file_version_info_mac.mm +++ b/base/file_version_info_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,7 +11,8 @@ #include "base/mac/mac_util.h" #include "base/sys_string_conversions.h" -FileVersionInfoMac::FileVersionInfoMac(NSBundle *bundle) : bundle_(bundle) { +FileVersionInfoMac::FileVersionInfoMac(NSBundle *bundle) + : bundle_([bundle retain]) { } FileVersionInfoMac::~FileVersionInfoMac() {} diff --git a/base/file_version_info_unittest.cc b/base/file_version_info_unittest.cc index 2b535c7..4184e04 100644 --- a/base/file_version_info_unittest.cc +++ b/base/file_version_info_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/file_util.h" +#include "base/memory/scoped_ptr.h" #include "base/path_service.h" -#include "base/scoped_ptr.h" #include "base/file_version_info.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/file_version_info_win.cc b/base/file_version_info_win.cc index 953caa9..8c6820e 100644 --- a/base/file_version_info_win.cc +++ b/base/file_version_info_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,9 +12,6 @@ #include "base/path_service.h" #include "base/threading/thread_restrictions.h" -// This has to be last. -#include <strsafe.h> - FileVersionInfoWin::FileVersionInfoWin(void* data, int language, int code_page) : language_(language), code_page_(code_page) { base::ThreadRestrictions::AssertIOAllowed(); diff --git a/base/file_version_info_win.h b/base/file_version_info_win.h index 4a49314..95652b0 100644 --- a/base/file_version_info_win.h +++ b/base/file_version_info_win.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,14 +8,15 @@ #include <string> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/file_version_info.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" struct tagVS_FIXEDFILEINFO; typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO; -class FileVersionInfoWin : public FileVersionInfo { +class BASE_API FileVersionInfoWin : public FileVersionInfo { public: FileVersionInfoWin(void* data, int language, int code_page); ~FileVersionInfoWin(); diff --git a/base/files/OWNERS b/base/files/OWNERS new file mode 100644 index 0000000..ef0b156 --- /dev/null +++ b/base/files/OWNERS @@ -0,0 +1,3 @@ +# for file_path_watcher* +mnissler@chromium.org +dmaclach@chromium.org diff --git a/base/files/file_path_watcher.cc b/base/files/file_path_watcher.cc new file mode 100644 index 0000000..7ce64ac --- /dev/null +++ b/base/files/file_path_watcher.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Cross platform methods for FilePathWatcher. See the various platform +// specific implementation files, too. + +#include "base/files/file_path_watcher.h" + +#include "base/logging.h" +#include "base/message_loop.h" + +namespace base { +namespace files { + +FilePathWatcher::~FilePathWatcher() { + impl_->Cancel(); +} + +bool FilePathWatcher::Watch(const FilePath& path, Delegate* delegate) { + DCHECK(path.IsAbsolute()); + return impl_->Watch(path, delegate); +} + +FilePathWatcher::PlatformDelegate::PlatformDelegate(): cancelled_(false) { +} + +FilePathWatcher::PlatformDelegate::~PlatformDelegate() { + DCHECK(is_cancelled()); +} + +} // namespace files +} // namespace base diff --git a/base/files/file_path_watcher.h b/base/files/file_path_watcher.h new file mode 100644 index 0000000..2cf95c6 --- /dev/null +++ b/base/files/file_path_watcher.h @@ -0,0 +1,128 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This module provides a way to monitor a file or directory for changes. + +#ifndef BASE_FILES_FILE_PATH_WATCHER_H_ +#define BASE_FILES_FILE_PATH_WATCHER_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop_proxy.h" + +namespace base { +namespace files { + +// This class lets you register interest in changes on a FilePath. +// The delegate will get called whenever the file or directory referenced by the +// FilePath is changed, including created or deleted. Due to limitations in the +// underlying OS APIs, FilePathWatcher has slightly different semantics on OS X +// than on Windows or Linux. FilePathWatcher on Linux and Windows will detect +// modifications to files in a watched directory. FilePathWatcher on Mac will +// detect the creation and deletion of files in a watched directory, but will +// not detect modifications to those files. See file_path_watcher_mac.cc for +// details. +class FilePathWatcher { + public: + // Declares the callback client code implements to receive notifications. Note + // that implementations of this interface should not keep a reference to the + // corresponding FileWatcher object to prevent a reference cycle. + class Delegate : public base::RefCountedThreadSafe<Delegate> { + public: + virtual ~Delegate() {} + virtual void OnFilePathChanged(const FilePath& path) = 0; + // Called when platform specific code detected an error. The watcher will + // not call OnFilePathChanged for future changes. + virtual void OnFilePathError(const FilePath& path) {} + }; + + FilePathWatcher(); + ~FilePathWatcher(); + + // Register interest in any changes on |path|. OnPathChanged will be called + // back for each change. Returns true on success. + // OnFilePathChanged() will be called on the same thread as Watch() is called, + // which should have a MessageLoop of TYPE_IO. + bool Watch(const FilePath& path, Delegate* delegate) WARN_UNUSED_RESULT; + + class PlatformDelegate; + + // A custom Task that always cleans up the PlatformDelegate, either when + // executed or when deleted without having been executed at all, as can + // happen during shutdown. + class CancelTask : public Task { + public: + CancelTask(PlatformDelegate* delegate): delegate_(delegate) {} + virtual ~CancelTask() { + delegate_->CancelOnMessageLoopThread(); + } + + virtual void Run() { + delegate_->CancelOnMessageLoopThread(); + } + private: + scoped_refptr<PlatformDelegate> delegate_; + + DISALLOW_COPY_AND_ASSIGN(CancelTask); + }; + + // Used internally to encapsulate different members on different platforms. + class PlatformDelegate : public base::RefCountedThreadSafe<PlatformDelegate> { + public: + PlatformDelegate(); + + // Start watching for the given |path| and notify |delegate| about changes. + virtual bool Watch(const FilePath& path, + Delegate* delegate) WARN_UNUSED_RESULT = 0; + + // Stop watching. This is called from FilePathWatcher's dtor in order to + // allow to shut down properly while the object is still alive. + // It can be called from any thread. + virtual void Cancel() = 0; + + protected: + virtual ~PlatformDelegate(); + + // Stop watching. This is only called on the thread of the appropriate + // message loop. Since it can also be called more than once, it should + // check |is_cancelled()| to avoid duplicate work. + virtual void CancelOnMessageLoopThread() = 0; + + scoped_refptr<base::MessageLoopProxy> message_loop() const { + return message_loop_; + } + + void set_message_loop(base::MessageLoopProxy* loop) { + message_loop_ = loop; + } + + // Must be called before the PlatformDelegate is deleted. + void set_cancelled() { + cancelled_ = true; + } + + bool is_cancelled() const { + return cancelled_; + } + + private: + friend class base::RefCountedThreadSafe<PlatformDelegate>; + friend class CancelTask; + + scoped_refptr<base::MessageLoopProxy> message_loop_; + bool cancelled_; + }; + + private: + scoped_refptr<PlatformDelegate> impl_; + + DISALLOW_COPY_AND_ASSIGN(FilePathWatcher); +}; + +} // namespace files +} // namespace base + +#endif // BASE_FILES_FILE_PATH_WATCHER_H_ diff --git a/base/files/file_path_watcher_browsertest.cc b/base/files/file_path_watcher_browsertest.cc new file mode 100644 index 0000000..d623c90 --- /dev/null +++ b/base/files/file_path_watcher_browsertest.cc @@ -0,0 +1,622 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/file_path_watcher.h" + +#include <set> + +#if defined(OS_WIN) +#include <windows.h> +#include <aclapi.h> +#elif defined(OS_POSIX) +#include <sys/stat.h> +#endif + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/memory/scoped_temp_dir.h" +#include "base/message_loop.h" +#include "base/message_loop_proxy.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "base/stl_util-inl.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/test_timeouts.h" +#include "base/threading/thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace files { + +namespace { + +class TestDelegate; + +// Aggregates notifications from the test delegates and breaks the message loop +// the test thread is waiting on once they all came in. +class NotificationCollector + : public base::RefCountedThreadSafe<NotificationCollector> { + public: + NotificationCollector() + : loop_(base::MessageLoopProxy::CreateForCurrentThread()) {} + + // Called from the file thread by the delegates. + void OnChange(TestDelegate* delegate) { + loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, + &NotificationCollector::RecordChange, + make_scoped_refptr(delegate))); + } + + void Register(TestDelegate* delegate) { + delegates_.insert(delegate); + } + + void Reset() { + signaled_.clear(); + } + + bool Success() { + return signaled_ == delegates_; + } + + private: + void RecordChange(TestDelegate* delegate) { + ASSERT_TRUE(loop_->BelongsToCurrentThread()); + ASSERT_TRUE(delegates_.count(delegate)); + signaled_.insert(delegate); + + // Check whether all delegates have been signaled. + if (signaled_ == delegates_) + loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + } + + // Set of registered delegates. + std::set<TestDelegate*> delegates_; + + // Set of signaled delegates. + std::set<TestDelegate*> signaled_; + + // The loop we should break after all delegates signaled. + scoped_refptr<base::MessageLoopProxy> loop_; +}; + +// A mock FilePathWatcher::Delegate for testing. I'd rather use gmock, but it's +// not thread safe for setting expectations, so the test code couldn't safely +// reset expectations while the file watcher is running. In order to allow this, +// we keep simple thread safe status flags in TestDelegate. +class TestDelegate : public FilePathWatcher::Delegate { + public: + // The message loop specified by |loop| will be quit if a notification is + // received while the delegate is |armed_|. Note that the testing code must + // guarantee |loop| outlives the file thread on which OnFilePathChanged runs. + explicit TestDelegate(NotificationCollector* collector) + : collector_(collector) { + collector_->Register(this); + } + + virtual void OnFilePathChanged(const FilePath&) { + collector_->OnChange(this); + } + + virtual void OnFilePathError(const FilePath& path) { + ADD_FAILURE() << "Error " << path.value(); + } + + private: + scoped_refptr<NotificationCollector> collector_; + + DISALLOW_COPY_AND_ASSIGN(TestDelegate); +}; + +// A helper class for setting up watches on the file thread. +class SetupWatchTask : public Task { + public: + SetupWatchTask(const FilePath& target, + FilePathWatcher* watcher, + FilePathWatcher::Delegate* delegate, + bool* result, + base::WaitableEvent* completion) + : target_(target), + watcher_(watcher), + delegate_(delegate), + result_(result), + completion_(completion) {} + + void Run() { + *result_ = watcher_->Watch(target_, delegate_); + completion_->Signal(); + } + + private: + const FilePath target_; + FilePathWatcher* watcher_; + FilePathWatcher::Delegate* delegate_; + bool* result_; + base::WaitableEvent* completion_; + + DISALLOW_COPY_AND_ASSIGN(SetupWatchTask); +}; + +class FilePathWatcherTest : public testing::Test { + public: + FilePathWatcherTest() + : file_thread_("FilePathWatcherTest") {} + + virtual ~FilePathWatcherTest() {} + + protected: + virtual void SetUp() { + // Create a separate file thread in order to test proper thread usage. + base::Thread::Options options(MessageLoop::TYPE_IO, 0); + ASSERT_TRUE(file_thread_.StartWithOptions(options)); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + collector_ = new NotificationCollector(); + } + + virtual void TearDown() { + loop_.RunAllPending(); + } + + FilePath test_file() { + return temp_dir_.path().AppendASCII("FilePathWatcherTest"); + } + + // Write |content| to |file|. Returns true on success. + bool WriteFile(const FilePath& file, const std::string& content) { + int write_size = file_util::WriteFile(file, content.c_str(), + content.length()); + return write_size == static_cast<int>(content.length()); + } + + bool SetupWatch(const FilePath& target, + FilePathWatcher* watcher, + FilePathWatcher::Delegate* delegate) WARN_UNUSED_RESULT { + base::WaitableEvent completion(false, false); + bool result; + file_thread_.message_loop_proxy()->PostTask(FROM_HERE, + new SetupWatchTask(target, + watcher, + delegate, + &result, + &completion)); + completion.Wait(); + return result; + } + + bool WaitForEvents() WARN_UNUSED_RESULT { + collector_->Reset(); + loop_.Run(); + return collector_->Success(); + } + + NotificationCollector* collector() { return collector_.get(); } + + MessageLoop loop_; + base::Thread file_thread_; + ScopedTempDir temp_dir_; + scoped_refptr<NotificationCollector> collector_; +}; + +// Basic test: Create the file and verify that we notice. +TEST_F(FilePathWatcherTest, NewFile) { + FilePathWatcher watcher; + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); + + ASSERT_TRUE(WriteFile(test_file(), "content")); + ASSERT_TRUE(WaitForEvents()); +} + +// Verify that modifying the file is caught. +TEST_F(FilePathWatcherTest, ModifiedFile) { + ASSERT_TRUE(WriteFile(test_file(), "content")); + + FilePathWatcher watcher; + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); + + // Now make sure we get notified if the file is modified. + ASSERT_TRUE(WriteFile(test_file(), "new content")); + ASSERT_TRUE(WaitForEvents()); +} + +// Verify that moving the file into place is caught. +TEST_F(FilePathWatcherTest, MovedFile) { + FilePath source_file(temp_dir_.path().AppendASCII("source")); + ASSERT_TRUE(WriteFile(source_file, "content")); + + FilePathWatcher watcher; + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); + + // Now make sure we get notified if the file is modified. + ASSERT_TRUE(file_util::Move(source_file, test_file())); + ASSERT_TRUE(WaitForEvents()); +} + +TEST_F(FilePathWatcherTest, DeletedFile) { + ASSERT_TRUE(WriteFile(test_file(), "content")); + + FilePathWatcher watcher; + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); + + // Now make sure we get notified if the file is deleted. + file_util::Delete(test_file(), false); + ASSERT_TRUE(WaitForEvents()); +} + +// Used by the DeleteDuringNotify test below. +// Deletes the FilePathWatcher when it's notified. +class Deleter : public FilePathWatcher::Delegate { + public: + Deleter(FilePathWatcher* watcher, MessageLoop* loop) + : watcher_(watcher), + loop_(loop) { + } + + virtual void OnFilePathChanged(const FilePath& path) { + watcher_.reset(); + loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + } + + scoped_ptr<FilePathWatcher> watcher_; + MessageLoop* loop_; +}; + +// Verify that deleting a watcher during the callback doesn't crash. +TEST_F(FilePathWatcherTest, DeleteDuringNotify) { + FilePathWatcher* watcher = new FilePathWatcher; + // Takes ownership of watcher. + scoped_refptr<Deleter> deleter(new Deleter(watcher, &loop_)); + ASSERT_TRUE(SetupWatch(test_file(), watcher, deleter.get())); + + ASSERT_TRUE(WriteFile(test_file(), "content")); + ASSERT_TRUE(WaitForEvents()); + + // We win if we haven't crashed yet. + // Might as well double-check it got deleted, too. + ASSERT_TRUE(deleter->watcher_.get() == NULL); +} + +// Verify that deleting the watcher works even if there is a pending +// notification. +TEST_F(FilePathWatcherTest, DestroyWithPendingNotification) { + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + FilePathWatcher* watcher = new FilePathWatcher; + ASSERT_TRUE(SetupWatch(test_file(), watcher, delegate.get())); + ASSERT_TRUE(WriteFile(test_file(), "content")); + file_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, watcher); +} + +TEST_F(FilePathWatcherTest, MultipleWatchersSingleFile) { + FilePathWatcher watcher1, watcher2; + scoped_refptr<TestDelegate> delegate1(new TestDelegate(collector())); + scoped_refptr<TestDelegate> delegate2(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher1, delegate1.get())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher2, delegate2.get())); + + ASSERT_TRUE(WriteFile(test_file(), "content")); + ASSERT_TRUE(WaitForEvents()); +} + +// Verify that watching a file whose parent directory doesn't exist yet works if +// the directory and file are created eventually. +TEST_F(FilePathWatcherTest, NonExistentDirectory) { + FilePathWatcher watcher; + FilePath dir(temp_dir_.path().AppendASCII("dir")); + FilePath file(dir.AppendASCII("file")); + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(file, &watcher, delegate.get())); + + ASSERT_TRUE(file_util::CreateDirectory(dir)); + + ASSERT_TRUE(WriteFile(file, "content")); + + VLOG(1) << "Waiting for file creation"; + ASSERT_TRUE(WaitForEvents()); + + ASSERT_TRUE(WriteFile(file, "content v2")); + VLOG(1) << "Waiting for file change"; + ASSERT_TRUE(WaitForEvents()); + + ASSERT_TRUE(file_util::Delete(file, false)); + VLOG(1) << "Waiting for file deletion"; + ASSERT_TRUE(WaitForEvents()); +} + +// Exercises watch reconfiguration for the case that directories on the path +// are rapidly created. +TEST_F(FilePathWatcherTest, DirectoryChain) { + FilePath path(temp_dir_.path()); + std::vector<std::string> dir_names; + for (int i = 0; i < 20; i++) { + std::string dir(StringPrintf("d%d", i)); + dir_names.push_back(dir); + path = path.AppendASCII(dir); + } + + FilePathWatcher watcher; + FilePath file(path.AppendASCII("file")); + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(file, &watcher, delegate.get())); + + FilePath sub_path(temp_dir_.path()); + for (std::vector<std::string>::const_iterator d(dir_names.begin()); + d != dir_names.end(); ++d) { + sub_path = sub_path.AppendASCII(*d); + ASSERT_TRUE(file_util::CreateDirectory(sub_path)); + } + VLOG(1) << "Create File"; + ASSERT_TRUE(WriteFile(file, "content")); + VLOG(1) << "Waiting for file creation"; + ASSERT_TRUE(WaitForEvents()); + + ASSERT_TRUE(WriteFile(file, "content v2")); + VLOG(1) << "Waiting for file modification"; + ASSERT_TRUE(WaitForEvents()); +} + +TEST_F(FilePathWatcherTest, DisappearingDirectory) { + FilePathWatcher watcher; + FilePath dir(temp_dir_.path().AppendASCII("dir")); + FilePath file(dir.AppendASCII("file")); + ASSERT_TRUE(file_util::CreateDirectory(dir)); + ASSERT_TRUE(WriteFile(file, "content")); + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(file, &watcher, delegate.get())); + + ASSERT_TRUE(file_util::Delete(dir, true)); + ASSERT_TRUE(WaitForEvents()); +} + +// Tests that a file that is deleted and reappears is tracked correctly. +TEST_F(FilePathWatcherTest, DeleteAndRecreate) { + ASSERT_TRUE(WriteFile(test_file(), "content")); + FilePathWatcher watcher; + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); + + ASSERT_TRUE(file_util::Delete(test_file(), false)); + VLOG(1) << "Waiting for file deletion"; + ASSERT_TRUE(WaitForEvents()); + + ASSERT_TRUE(WriteFile(test_file(), "content")); + VLOG(1) << "Waiting for file creation"; + ASSERT_TRUE(WaitForEvents()); +} + +TEST_F(FilePathWatcherTest, WatchDirectory) { + FilePathWatcher watcher; + FilePath dir(temp_dir_.path().AppendASCII("dir")); + FilePath file1(dir.AppendASCII("file1")); + FilePath file2(dir.AppendASCII("file2")); + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(dir, &watcher, delegate.get())); + + ASSERT_TRUE(file_util::CreateDirectory(dir)); + VLOG(1) << "Waiting for directory creation"; + ASSERT_TRUE(WaitForEvents()); + + ASSERT_TRUE(WriteFile(file1, "content")); + VLOG(1) << "Waiting for file1 creation"; + ASSERT_TRUE(WaitForEvents()); + +#if !defined(OS_MACOSX) + // Mac implementation does not detect files modified in a directory. + ASSERT_TRUE(WriteFile(file1, "content v2")); + VLOG(1) << "Waiting for file1 modification"; + ASSERT_TRUE(WaitForEvents()); +#endif // !OS_MACOSX + + ASSERT_TRUE(file_util::Delete(file1, false)); + VLOG(1) << "Waiting for file1 deletion"; + ASSERT_TRUE(WaitForEvents()); + + ASSERT_TRUE(WriteFile(file2, "content")); + VLOG(1) << "Waiting for file2 creation"; + ASSERT_TRUE(WaitForEvents()); +} + +TEST_F(FilePathWatcherTest, MoveParent) { + FilePathWatcher file_watcher; + FilePathWatcher subdir_watcher; + FilePath dir(temp_dir_.path().AppendASCII("dir")); + FilePath dest(temp_dir_.path().AppendASCII("dest")); + FilePath subdir(dir.AppendASCII("subdir")); + FilePath file(subdir.AppendASCII("file")); + scoped_refptr<TestDelegate> file_delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(file, &file_watcher, file_delegate.get())); + scoped_refptr<TestDelegate> subdir_delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(subdir, &subdir_watcher, subdir_delegate.get())); + + // Setup a directory hierarchy. + ASSERT_TRUE(file_util::CreateDirectory(subdir)); + ASSERT_TRUE(WriteFile(file, "content")); + VLOG(1) << "Waiting for file creation"; + ASSERT_TRUE(WaitForEvents()); + + // Move the parent directory. + file_util::Move(dir, dest); + VLOG(1) << "Waiting for directory move"; + ASSERT_TRUE(WaitForEvents()); +} + +TEST_F(FilePathWatcherTest, MoveChild) { + FilePathWatcher file_watcher; + FilePathWatcher subdir_watcher; + FilePath source_dir(temp_dir_.path().AppendASCII("source")); + FilePath source_subdir(source_dir.AppendASCII("subdir")); + FilePath source_file(source_subdir.AppendASCII("file")); + FilePath dest_dir(temp_dir_.path().AppendASCII("dest")); + FilePath dest_subdir(dest_dir.AppendASCII("subdir")); + FilePath dest_file(dest_subdir.AppendASCII("file")); + + // Setup a directory hierarchy. + ASSERT_TRUE(file_util::CreateDirectory(source_subdir)); + ASSERT_TRUE(WriteFile(source_file, "content")); + + scoped_refptr<TestDelegate> file_delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(dest_file, &file_watcher, file_delegate.get())); + scoped_refptr<TestDelegate> subdir_delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(dest_subdir, &subdir_watcher, subdir_delegate.get())); + + // Move the directory into place, s.t. the watched file appears. + ASSERT_TRUE(file_util::Move(source_dir, dest_dir)); + ASSERT_TRUE(WaitForEvents()); +} + +#if !defined(OS_LINUX) +// Linux implementation of FilePathWatcher doesn't catch attribute changes. +// http://crbug.com/78043 + +// Verify that changing attributes on a file is caught +TEST_F(FilePathWatcherTest, FileAttributesChanged) { + ASSERT_TRUE(WriteFile(test_file(), "content")); + FilePathWatcher watcher; + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); + + // Now make sure we get notified if the file is modified. + ASSERT_TRUE(file_util::MakeFileUnreadable(test_file())); + ASSERT_TRUE(WaitForEvents()); +} + +#endif // !OS_LINUX + +enum Permission { + Read, + Write, + Execute +}; + +bool ChangeFilePermissions(const FilePath& path, Permission perm, bool allow) { +#if defined(OS_POSIX) + struct stat stat_buf; + + if (stat(path.value().c_str(), &stat_buf) != 0) + return false; + + mode_t mode = 0; + switch (perm) { + case Read: + mode = S_IRUSR | S_IRGRP | S_IROTH; + break; + case Write: + mode = S_IWUSR | S_IWGRP | S_IWOTH; + break; + case Execute: + mode = S_IXUSR | S_IXGRP | S_IXOTH; + break; + default: + ADD_FAILURE() << "unknown perm " << perm; + return false; + } + if (allow) { + stat_buf.st_mode |= mode; + } else { + stat_buf.st_mode &= ~mode; + } + return chmod(path.value().c_str(), stat_buf.st_mode) == 0; + +#elif defined(OS_WIN) + PACL old_dacl; + PSECURITY_DESCRIPTOR security_descriptor; + if (GetNamedSecurityInfo(const_cast<wchar_t*>(path.value().c_str()), + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, NULL, NULL, &old_dacl, + NULL, &security_descriptor) != ERROR_SUCCESS) + return false; + + DWORD mode = 0; + switch (perm) { + case Read: + mode = GENERIC_READ; + break; + case Write: + mode = GENERIC_WRITE; + break; + case Execute: + mode = GENERIC_EXECUTE; + break; + default: + ADD_FAILURE() << "unknown perm " << perm; + return false; + } + + // Deny Read access for the current user. + EXPLICIT_ACCESS change; + change.grfAccessPermissions = mode; + change.grfAccessMode = allow ? GRANT_ACCESS : DENY_ACCESS; + change.grfInheritance = 0; + change.Trustee.pMultipleTrustee = NULL; + change.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + change.Trustee.TrusteeForm = TRUSTEE_IS_NAME; + change.Trustee.TrusteeType = TRUSTEE_IS_USER; + change.Trustee.ptstrName = L"CURRENT_USER"; + + PACL new_dacl; + if (SetEntriesInAcl(1, &change, old_dacl, &new_dacl) != ERROR_SUCCESS) { + LocalFree(security_descriptor); + return false; + } + + DWORD rc = SetNamedSecurityInfo(const_cast<wchar_t*>(path.value().c_str()), + SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, + NULL, NULL, new_dacl, NULL); + LocalFree(security_descriptor); + LocalFree(new_dacl); + + return rc == ERROR_SUCCESS; +#else + NOTIMPLEMENTED(); + return false; +#endif +} + +#if defined(OS_MACOSX) +// Linux implementation of FilePathWatcher doesn't catch attribute changes. +// http://crbug.com/78043 +// Windows implementation of FilePathWatcher catches attribute changes that +// don't affect the path being watched. +// http://crbug.com/78045 + +// Verify that changing attributes on a directory works. +TEST_F(FilePathWatcherTest, DirAttributesChanged) { + FilePath test_dir1(temp_dir_.path().AppendASCII("DirAttributesChangedDir1")); + FilePath test_dir2(test_dir1.AppendASCII("DirAttributesChangedDir2")); + FilePath test_file(test_dir2.AppendASCII("DirAttributesChangedFile")); + // Setup a directory hierarchy. + ASSERT_TRUE(file_util::CreateDirectory(test_dir1)); + ASSERT_TRUE(file_util::CreateDirectory(test_dir2)); + ASSERT_TRUE(WriteFile(test_file, "content")); + + FilePathWatcher watcher; + scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); + ASSERT_TRUE(SetupWatch(test_file, &watcher, delegate.get())); + + // We should not get notified in this case as it hasn't affected our ability + // to access the file. + ASSERT_TRUE(ChangeFilePermissions(test_dir1, Read, false)); + loop_.PostDelayedTask(FROM_HERE, + new MessageLoop::QuitTask, + TestTimeouts::tiny_timeout_ms()); + ASSERT_FALSE(WaitForEvents()); + ASSERT_TRUE(ChangeFilePermissions(test_dir1, Read, true)); + + // We should get notified in this case because filepathwatcher can no + // longer access the file + ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, false)); + ASSERT_TRUE(WaitForEvents()); + ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, true)); +} + +#endif // OS_MACOSX +} // namespace + +} // namespace files +} // namespace base diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc new file mode 100644 index 0000000..0fb10e4 --- /dev/null +++ b/base/files/file_path_watcher_linux.cc @@ -0,0 +1,462 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/file_path_watcher.h" + +#include <errno.h> +#include <string.h> +#include <sys/inotify.h> +#include <sys/ioctl.h> +#include <sys/select.h> +#include <unistd.h> + +#include <algorithm> +#include <set> +#include <utility> +#include <vector> + +#include "base/eintr_wrapper.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/hash_tables.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/message_loop_proxy.h" +#include "base/synchronization/lock.h" +#include "base/task.h" +#include "base/threading/thread.h" + +namespace base { +namespace files { + +namespace { + +class FilePathWatcherImpl; + +// Singleton to manage all inotify watches. +// TODO(tony): It would be nice if this wasn't a singleton. +// http://crbug.com/38174 +class InotifyReader { + public: + typedef int Watch; // Watch descriptor used by AddWatch and RemoveWatch. + static const Watch kInvalidWatch = -1; + + // Watch directory |path| for changes. |watcher| will be notified on each + // change. Returns kInvalidWatch on failure. + Watch AddWatch(const FilePath& path, FilePathWatcherImpl* watcher); + + // Remove |watch|. Returns true on success. + bool RemoveWatch(Watch watch, FilePathWatcherImpl* watcher); + + // Callback for InotifyReaderTask. + void OnInotifyEvent(const inotify_event* event); + + private: + friend struct ::base::DefaultLazyInstanceTraits<InotifyReader>; + + typedef std::set<FilePathWatcherImpl*> WatcherSet; + + InotifyReader(); + ~InotifyReader(); + + // We keep track of which delegates want to be notified on which watches. + base::hash_map<Watch, WatcherSet> watchers_; + + // Lock to protect watchers_. + base::Lock lock_; + + // Separate thread on which we run blocking read for inotify events. + base::Thread thread_; + + // File descriptor returned by inotify_init. + const int inotify_fd_; + + // Use self-pipe trick to unblock select during shutdown. + int shutdown_pipe_[2]; + + // Flag set to true when startup was successful. + bool valid_; + + DISALLOW_COPY_AND_ASSIGN(InotifyReader); +}; + +class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate, + public MessageLoop::DestructionObserver { + public: + FilePathWatcherImpl(); + + // Called for each event coming from the watch. |fired_watch| identifies the + // watch that fired, |child| indicates what has changed, and is relative to + // the currently watched path for |fired_watch|. The flag |created| is true if + // the object appears, and |is_directory| is set when the event refers to a + // directory. + void OnFilePathChanged(InotifyReader::Watch fired_watch, + const FilePath::StringType& child, + bool created, + bool is_directory); + + // Start watching |path| for changes and notify |delegate| on each change. + // Returns true if watch for |path| has been added successfully. + virtual bool Watch(const FilePath& path, + FilePathWatcher::Delegate* delegate) OVERRIDE; + + // Cancel the watch. This unregisters the instance with InotifyReader. + virtual void Cancel() OVERRIDE; + + // Deletion of the FilePathWatcher will call Cancel() to dispose of this + // object in the right thread. This also observes destruction of the required + // cleanup thread, in case it quits before Cancel() is called. + virtual void WillDestroyCurrentMessageLoop() OVERRIDE; + + private: + virtual ~FilePathWatcherImpl() {} + + // Cleans up and stops observing the |message_loop_| thread. + void CancelOnMessageLoopThread() OVERRIDE; + + // Inotify watches are installed for all directory components of |target_|. A + // WatchEntry instance holds the watch descriptor for a component and the + // subdirectory for that identifies the next component. + struct WatchEntry { + WatchEntry(InotifyReader::Watch watch, const FilePath::StringType& subdir) + : watch_(watch), + subdir_(subdir) {} + + InotifyReader::Watch watch_; + FilePath::StringType subdir_; + }; + typedef std::vector<WatchEntry> WatchVector; + + // Reconfigure to watch for the most specific parent directory of |target_| + // that exists. Updates |watched_path_|. Returns true on success. + bool UpdateWatches() WARN_UNUSED_RESULT; + + // Delegate to notify upon changes. + scoped_refptr<FilePathWatcher::Delegate> delegate_; + + // The file or directory we're supposed to watch. + FilePath target_; + + // The vector of watches and next component names for all path components, + // starting at the root directory. The last entry corresponds to the watch for + // |target_| and always stores an empty next component name in |subdir_|. + WatchVector watches_; + + DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); +}; + +class InotifyReaderTask : public Task { + public: + InotifyReaderTask(InotifyReader* reader, int inotify_fd, int shutdown_fd) + : reader_(reader), + inotify_fd_(inotify_fd), + shutdown_fd_(shutdown_fd) { + } + + virtual void Run() { + while (true) { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(inotify_fd_, &rfds); + FD_SET(shutdown_fd_, &rfds); + + // Wait until some inotify events are available. + int select_result = + HANDLE_EINTR(select(std::max(inotify_fd_, shutdown_fd_) + 1, + &rfds, NULL, NULL, NULL)); + if (select_result < 0) { + DPLOG(WARNING) << "select failed"; + return; + } + + if (FD_ISSET(shutdown_fd_, &rfds)) + return; + + // Adjust buffer size to current event queue size. + int buffer_size; + int ioctl_result = HANDLE_EINTR(ioctl(inotify_fd_, FIONREAD, + &buffer_size)); + + if (ioctl_result != 0) { + DPLOG(WARNING) << "ioctl failed"; + return; + } + + std::vector<char> buffer(buffer_size); + + ssize_t bytes_read = HANDLE_EINTR(read(inotify_fd_, &buffer[0], + buffer_size)); + + if (bytes_read < 0) { + DPLOG(WARNING) << "read from inotify fd failed"; + return; + } + + ssize_t i = 0; + while (i < bytes_read) { + inotify_event* event = reinterpret_cast<inotify_event*>(&buffer[i]); + size_t event_size = sizeof(inotify_event) + event->len; + DCHECK(i + event_size <= static_cast<size_t>(bytes_read)); + reader_->OnInotifyEvent(event); + i += event_size; + } + } + } + + private: + InotifyReader* reader_; + int inotify_fd_; + int shutdown_fd_; + + DISALLOW_COPY_AND_ASSIGN(InotifyReaderTask); +}; + +static base::LazyInstance<InotifyReader> g_inotify_reader( + base::LINKER_INITIALIZED); + +InotifyReader::InotifyReader() + : thread_("inotify_reader"), + inotify_fd_(inotify_init()), + valid_(false) { + shutdown_pipe_[0] = -1; + shutdown_pipe_[1] = -1; + if (inotify_fd_ >= 0 && pipe(shutdown_pipe_) == 0 && thread_.Start()) { + thread_.message_loop()->PostTask( + FROM_HERE, new InotifyReaderTask(this, inotify_fd_, shutdown_pipe_[0])); + valid_ = true; + } +} + +InotifyReader::~InotifyReader() { + if (valid_) { + // Write to the self-pipe so that the select call in InotifyReaderTask + // returns. + ssize_t ret = HANDLE_EINTR(write(shutdown_pipe_[1], "", 1)); + DPCHECK(ret > 0); + DCHECK_EQ(ret, 1); + thread_.Stop(); + } + if (inotify_fd_ >= 0) + close(inotify_fd_); + if (shutdown_pipe_[0] >= 0) + close(shutdown_pipe_[0]); + if (shutdown_pipe_[1] >= 0) + close(shutdown_pipe_[1]); +} + +InotifyReader::Watch InotifyReader::AddWatch( + const FilePath& path, FilePathWatcherImpl* watcher) { + if (!valid_) + return kInvalidWatch; + + base::AutoLock auto_lock(lock_); + + Watch watch = inotify_add_watch(inotify_fd_, path.value().c_str(), + IN_CREATE | IN_DELETE | + IN_CLOSE_WRITE | IN_MOVE | + IN_ONLYDIR); + + if (watch == kInvalidWatch) + return kInvalidWatch; + + watchers_[watch].insert(watcher); + + return watch; +} + +bool InotifyReader::RemoveWatch(Watch watch, + FilePathWatcherImpl* watcher) { + if (!valid_) + return false; + + base::AutoLock auto_lock(lock_); + + watchers_[watch].erase(watcher); + + if (watchers_[watch].empty()) { + watchers_.erase(watch); + return (inotify_rm_watch(inotify_fd_, watch) == 0); + } + + return true; +} + +void InotifyReader::OnInotifyEvent(const inotify_event* event) { + if (event->mask & IN_IGNORED) + return; + + FilePath::StringType child(event->len ? event->name : FILE_PATH_LITERAL("")); + base::AutoLock auto_lock(lock_); + + for (WatcherSet::iterator watcher = watchers_[event->wd].begin(); + watcher != watchers_[event->wd].end(); + ++watcher) { + (*watcher)->OnFilePathChanged(event->wd, + child, + event->mask & (IN_CREATE | IN_MOVED_TO), + event->mask & IN_ISDIR); + } +} + +FilePathWatcherImpl::FilePathWatcherImpl() + : delegate_(NULL) { +} + +void FilePathWatcherImpl::OnFilePathChanged( + InotifyReader::Watch fired_watch, + const FilePath::StringType& child, + bool created, + bool is_directory) { + + if (!message_loop()->BelongsToCurrentThread()) { + // Switch to message_loop_ to access watches_ safely. + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, + &FilePathWatcherImpl::OnFilePathChanged, + fired_watch, + child, + created, + is_directory)); + return; + } + + DCHECK(MessageLoopForIO::current()); + + // Find the entry in |watches_| that corresponds to |fired_watch|. + WatchVector::const_iterator watch_entry(watches_.begin()); + for ( ; watch_entry != watches_.end(); ++watch_entry) { + if (fired_watch == watch_entry->watch_) + break; + } + + // If this notification is from a previous generation of watches or the watch + // has been cancelled (|watches_| is empty then), bail out. + if (watch_entry == watches_.end()) + return; + + // Check whether a path component of |target_| changed. + bool change_on_target_path = child.empty() || child == watch_entry->subdir_; + + // Check whether the change references |target_| or a direct child. + DCHECK(watch_entry->subdir_.empty() || (watch_entry + 1) != watches_.end()); + bool target_changed = watch_entry->subdir_.empty() || + (watch_entry->subdir_ == child && (++watch_entry)->subdir_.empty()); + + // Update watches if a directory component of the |target_| path (dis)appears. + if (is_directory && change_on_target_path && !UpdateWatches()) { + delegate_->OnFilePathError(target_); + return; + } + + // Report the following events: + // - The target or a direct child of the target got changed (in case the + // watched path refers to a directory). + // - One of the parent directories got moved or deleted, since the target + // disappears in this case. + // - One of the parent directories appears. The event corresponding to the + // target appearing might have been missed in this case, so recheck. + if (target_changed || + (change_on_target_path && !created) || + (change_on_target_path && file_util::PathExists(target_))) { + delegate_->OnFilePathChanged(target_); + } +} + +bool FilePathWatcherImpl::Watch(const FilePath& path, + FilePathWatcher::Delegate* delegate) { + DCHECK(target_.empty()); + DCHECK(MessageLoopForIO::current()); + + set_message_loop(base::MessageLoopProxy::CreateForCurrentThread()); + delegate_ = delegate; + target_ = path; + MessageLoop::current()->AddDestructionObserver(this); + + std::vector<FilePath::StringType> comps; + target_.GetComponents(&comps); + DCHECK(!comps.empty()); + for (std::vector<FilePath::StringType>::const_iterator comp(++comps.begin()); + comp != comps.end(); ++comp) { + watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, *comp)); + } + watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, + FilePath::StringType())); + return UpdateWatches(); +} + +void FilePathWatcherImpl::Cancel() { + if (!delegate_) { + // Watch was never called, or the |message_loop_| thread is already gone. + set_cancelled(); + return; + } + + // Switch to the message_loop_ if necessary so we can access |watches_|. + if (!message_loop()->BelongsToCurrentThread()) { + message_loop()->PostTask(FROM_HERE, + new FilePathWatcher::CancelTask(this)); + } else { + CancelOnMessageLoopThread(); + } +} + +void FilePathWatcherImpl::CancelOnMessageLoopThread() { + if (!is_cancelled()) { + set_cancelled(); + MessageLoop::current()->RemoveDestructionObserver(this); + + for (WatchVector::iterator watch_entry(watches_.begin()); + watch_entry != watches_.end(); ++watch_entry) { + if (watch_entry->watch_ != InotifyReader::kInvalidWatch) + g_inotify_reader.Get().RemoveWatch(watch_entry->watch_, this); + } + watches_.clear(); + delegate_ = NULL; + target_.clear(); + } +} + +void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() { + CancelOnMessageLoopThread(); +} + +bool FilePathWatcherImpl::UpdateWatches() { + // Ensure this runs on the message_loop_ exclusively in order to avoid + // concurrency issues. + DCHECK(message_loop()->BelongsToCurrentThread()); + + // Walk the list of watches and update them as we go. + FilePath path(FILE_PATH_LITERAL("/")); + bool path_valid = true; + for (WatchVector::iterator watch_entry(watches_.begin()); + watch_entry != watches_.end(); ++watch_entry) { + InotifyReader::Watch old_watch = watch_entry->watch_; + if (path_valid) { + watch_entry->watch_ = g_inotify_reader.Get().AddWatch(path, this); + if (watch_entry->watch_ == InotifyReader::kInvalidWatch) { + path_valid = false; + } + } else { + watch_entry->watch_ = InotifyReader::kInvalidWatch; + } + if (old_watch != InotifyReader::kInvalidWatch && + old_watch != watch_entry->watch_) { + g_inotify_reader.Get().RemoveWatch(old_watch, this); + } + path = path.Append(watch_entry->subdir_); + } + + return true; +} + +} // namespace + +FilePathWatcher::FilePathWatcher() { + impl_ = new FilePathWatcherImpl(); +} + +} // namespace files +} // namespace base diff --git a/base/files/file_path_watcher_mac.cc b/base/files/file_path_watcher_mac.cc new file mode 100644 index 0000000..7b61f76 --- /dev/null +++ b/base/files/file_path_watcher_mac.cc @@ -0,0 +1,493 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/file_path_watcher.h" + +#include <fcntl.h> +#include <sys/event.h> +#include <sys/param.h> + +#include <vector> + +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/message_loop_proxy.h" +#include "base/stringprintf.h" + +namespace base { +namespace files { + +namespace { + +// Mac-specific file watcher implementation based on kqueue. +// Originally it was based on FSEvents so that the semantics were equivalent +// on Linux, OSX and Windows where it was able to detect: +// - file creation/deletion/modification in a watched directory +// - file creation/deletion/modification for a watched file +// - modifications to the paths to a watched object that would affect the +// object such as renaming/attibute changes etc. +// The FSEvents version did all of the above except handling attribute changes +// to path components. Unfortunately FSEvents appears to have an issue where the +// current implementation (Mac OS X 10.6.7) sometimes drops events and doesn't +// send notifications. See +// http://code.google.com/p/chromium/issues/detail?id=54822#c31 for source that +// will reproduce the problem. FSEvents also required having a CFRunLoop +// backing the thread that it was running on, that caused added complexity +// in the interfaces. +// The kqueue implementation will handle all of the items in the list above +// except for detecting modifications to files in a watched directory. It will +// detect the creation and deletion of files, just not the modification of +// files. It does however detect the attribute changes that the FSEvents impl +// would miss. +class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate, + public MessageLoopForIO::Watcher, + public MessageLoop::DestructionObserver { + public: + FilePathWatcherImpl() : kqueue_(-1) {} + virtual ~FilePathWatcherImpl() {} + + // MessageLoopForIO::Watcher overrides. + virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; + virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; + + // MessageLoop::DestructionObserver overrides. + virtual void WillDestroyCurrentMessageLoop() OVERRIDE; + + // FilePathWatcher::PlatformDelegate overrides. + virtual bool Watch(const FilePath& path, + FilePathWatcher::Delegate* delegate) OVERRIDE; + virtual void Cancel() OVERRIDE; + + private: + class EventData { + public: + EventData(const FilePath& path, const FilePath::StringType& subdir) + : path_(path), subdir_(subdir) { } + FilePath path_; // Full path to this item. + FilePath::StringType subdir_; // Path to any sub item. + }; + typedef std::vector<struct kevent> EventVector; + + // Can only be called on |io_message_loop_|'s thread. + virtual void CancelOnMessageLoopThread() OVERRIDE; + + // Returns true if the kevent values are error free. + bool AreKeventValuesValid(struct kevent* kevents, int count); + + // Respond to a change of attributes of the path component represented by + // |event|. Sets |target_file_affected| to true if |target_| is affected. + // Sets |update_watches| to true if |events_| need to be updated. + void HandleAttributesChange(const EventVector::iterator& event, + bool* target_file_affected, + bool* update_watches); + + // Respond to a move of deletion of the path component represented by + // |event|. Sets |target_file_affected| to true if |target_| is affected. + // Sets |update_watches| to true if |events_| need to be updated. + void HandleDeleteOrMoveChange(const EventVector::iterator& event, + bool* target_file_affected, + bool* update_watches); + + // Respond to a creation of an item in the path component represented by + // |event|. Sets |target_file_affected| to true if |target_| is affected. + // Sets |update_watches| to true if |events_| need to be updated. + void HandleCreateItemChange(const EventVector::iterator& event, + bool* target_file_affected, + bool* update_watches); + + // Update |events_| with the current status of the system. + // Sets |target_file_affected| to true if |target_| is affected. + // Returns false if an error occurs. + bool UpdateWatches(bool* target_file_affected); + + // Fills |events| with one kevent per component in |path|. + // Returns the number of valid events created where a valid event is + // defined as one that has a ident (file descriptor) field != -1. + static int EventsForPath(FilePath path, EventVector *events); + + // Release a kevent generated by EventsForPath. + static void ReleaseEvent(struct kevent& event); + + // Returns a file descriptor that will not block the system from deleting + // the file it references. + static int FileDescriptorForPath(const FilePath& path); + + // Closes |*fd| and sets |*fd| to -1. + static void CloseFileDescriptor(int* fd); + + // Returns true if kevent has open file descriptor. + static bool IsKeventFileDescriptorOpen(const struct kevent& event) { + return event.ident != static_cast<uintptr_t>(-1); + } + + static EventData* EventDataForKevent(const struct kevent& event) { + return reinterpret_cast<EventData*>(event.udata); + } + + EventVector events_; + scoped_refptr<base::MessageLoopProxy> io_message_loop_; + MessageLoopForIO::FileDescriptorWatcher kqueue_watcher_; + scoped_refptr<FilePathWatcher::Delegate> delegate_; + FilePath target_; + int kqueue_; + + DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); +}; + +void FilePathWatcherImpl::ReleaseEvent(struct kevent& event) { + CloseFileDescriptor(reinterpret_cast<int*>(&event.ident)); + EventData* entry = EventDataForKevent(event); + delete entry; + event.udata = NULL; +} + +int FilePathWatcherImpl::EventsForPath(FilePath path, EventVector* events) { + DCHECK(MessageLoopForIO::current()); + // Make sure that we are working with a clean slate. + DCHECK(events->empty()); + + std::vector<FilePath::StringType> components; + path.GetComponents(&components); + + if (components.size() < 1) { + return -1; + } + + int last_existing_entry = 0; + FilePath built_path; + bool path_still_exists = true; + for(std::vector<FilePath::StringType>::iterator i = components.begin(); + i != components.end(); ++i) { + if (i == components.begin()) { + built_path = FilePath(*i); + } else { + built_path = built_path.Append(*i); + } + int fd = -1; + if (path_still_exists) { + fd = FileDescriptorForPath(built_path); + if (fd == -1) { + path_still_exists = false; + } else { + ++last_existing_entry; + } + } + FilePath::StringType subdir = (i != (components.end() - 1)) ? *(i + 1) : ""; + EventData* data = new EventData(built_path, subdir); + struct kevent event; + EV_SET(&event, fd, EVFILT_VNODE, (EV_ADD | EV_CLEAR | EV_RECEIPT), + (NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB | + NOTE_RENAME | NOTE_REVOKE | NOTE_EXTEND), 0, data); + events->push_back(event); + } + return last_existing_entry; +} + +int FilePathWatcherImpl::FileDescriptorForPath(const FilePath& path) { + return HANDLE_EINTR(open(path.value().c_str(), O_EVTONLY)); +} + +void FilePathWatcherImpl::CloseFileDescriptor(int *fd) { + if (*fd == -1) { + return; + } + + if (HANDLE_EINTR(close(*fd)) != 0) { + PLOG(ERROR) << "close"; + } + *fd = -1; +} + +bool FilePathWatcherImpl::AreKeventValuesValid(struct kevent* kevents, + int count) { + if (count < 0) { + PLOG(ERROR) << "kevent"; + return false; + } + bool valid = true; + for (int i = 0; i < count; ++i) { + if (kevents[i].flags & EV_ERROR && kevents[i].data) { + // Find the kevent in |events_| that matches the kevent with the error. + EventVector::iterator event = events_.begin(); + for (; event != events_.end(); ++event) { + if (event->ident == kevents[i].ident) { + break; + } + } + std::string path_name; + if (event != events_.end()) { + EventData* event_data = EventDataForKevent(*event); + if (event_data != NULL) { + path_name = event_data->path_.value(); + } + } + if (path_name.empty()) { + path_name = base::StringPrintf( + "fd %d", *reinterpret_cast<int*>(&kevents[i].ident)); + } + LOG(ERROR) << "Error: " << kevents[i].data << " for " << path_name; + valid = false; + } + } + return valid; +} + +void FilePathWatcherImpl::HandleAttributesChange( + const EventVector::iterator& event, + bool* target_file_affected, + bool* update_watches) { + EventVector::iterator next_event = event + 1; + EventData* next_event_data = EventDataForKevent(*next_event); + // Check to see if the next item in path is still accessible. + int have_access = FileDescriptorForPath(next_event_data->path_); + if (have_access == -1) { + *target_file_affected = true; + *update_watches = true; + EventVector::iterator local_event(event); + for (; local_event != events_.end(); ++local_event) { + // Close all nodes from the event down. This has the side effect of + // potentially rendering other events in |updates| invalid. + // There is no need to remove the events from |kqueue_| because this + // happens as a side effect of closing the file descriptor. + CloseFileDescriptor(reinterpret_cast<int*>(&local_event->ident)); + } + } else { + CloseFileDescriptor(&have_access); + } +} + +void FilePathWatcherImpl::HandleDeleteOrMoveChange( + const EventVector::iterator& event, + bool* target_file_affected, + bool* update_watches) { + *target_file_affected = true; + *update_watches = true; + EventVector::iterator local_event(event); + for (; local_event != events_.end(); ++local_event) { + // Close all nodes from the event down. This has the side effect of + // potentially rendering other events in |updates| invalid. + // There is no need to remove the events from |kqueue_| because this + // happens as a side effect of closing the file descriptor. + CloseFileDescriptor(reinterpret_cast<int*>(&local_event->ident)); + } +} + +void FilePathWatcherImpl::HandleCreateItemChange( + const EventVector::iterator& event, + bool* target_file_affected, + bool* update_watches) { + // Get the next item in the path. + EventVector::iterator next_event = event + 1; + EventData* next_event_data = EventDataForKevent(*next_event); + + // Check to see if it already has a valid file descriptor. + if (!IsKeventFileDescriptorOpen(*next_event)) { + // If not, attempt to open a file descriptor for it. + next_event->ident = FileDescriptorForPath(next_event_data->path_); + if (IsKeventFileDescriptorOpen(*next_event)) { + *update_watches = true; + if (next_event_data->subdir_.empty()) { + *target_file_affected = true; + } + } + } +} + +bool FilePathWatcherImpl::UpdateWatches(bool* target_file_affected) { + // Iterate over events adding kevents for items that exist to the kqueue. + // Then check to see if new components in the path have been created. + // Repeat until no new components in the path are detected. + // This is to get around races in directory creation in a watched path. + bool update_watches = true; + while (update_watches) { + size_t valid; + for (valid = 0; valid < events_.size(); ++valid) { + if (!IsKeventFileDescriptorOpen(events_[valid])) { + break; + } + } + if (valid == 0) { + // The root of the file path is inaccessible? + return false; + } + + EventVector updates(valid); + int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], valid, &updates[0], + valid, NULL)); + if (!AreKeventValuesValid(&updates[0], count)) { + return false; + } + update_watches = false; + for (; valid < events_.size(); ++valid) { + EventData* event_data = EventDataForKevent(events_[valid]); + events_[valid].ident = FileDescriptorForPath(event_data->path_); + if (IsKeventFileDescriptorOpen(events_[valid])) { + update_watches = true; + if (event_data->subdir_.empty()) { + *target_file_affected = true; + } + } else { + break; + } + } + } + return true; +} + +void FilePathWatcherImpl::OnFileCanReadWithoutBlocking(int fd) { + DCHECK(MessageLoopForIO::current()); + CHECK_EQ(fd, kqueue_); + CHECK(events_.size()); + + // Request the file system update notifications that have occurred and return + // them in |updates|. |count| will contain the number of updates that have + // occurred. + EventVector updates(events_.size()); + struct timespec timeout = {0, 0}; + int count = HANDLE_EINTR(kevent(kqueue_, NULL, 0, &updates[0], updates.size(), + &timeout)); + + // Error values are stored within updates, so check to make sure that no + // errors occurred. + if (!AreKeventValuesValid(&updates[0], count)) { + delegate_->OnFilePathError(target_); + Cancel(); + return; + } + + bool update_watches = false; + bool send_notification = false; + + // Iterate through each of the updates and react to them. + for (int i = 0; i < count; ++i) { + // Find our kevent record that matches the update notification. + EventVector::iterator event = events_.begin(); + for (; event != events_.end(); ++event) { + if (!IsKeventFileDescriptorOpen(*event) || + event->ident == updates[i].ident) { + break; + } + } + if (!IsKeventFileDescriptorOpen(*event) || event == events_.end()) { + // The event may no longer exist in |events_| because another event + // modified |events_| in such a way to make it invalid. For example if + // the path is /foo/bar/bam and foo is deleted, NOTE_DELETE events for + // foo, bar and bam will be sent. If foo is processed first, then + // the file descriptors for bar and bam will already be closed and set + // to -1 before they get a chance to be processed. + continue; + } + + EventData* event_data = EventDataForKevent(*event); + + // If the subdir is empty, this is the last item on the path and is the + // target file. + bool target_file_affected = event_data->subdir_.empty(); + if ((updates[i].fflags & NOTE_ATTRIB) && !target_file_affected) { + HandleAttributesChange(event, &target_file_affected, &update_watches); + } + if (updates[i].fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) { + HandleDeleteOrMoveChange(event, &target_file_affected, &update_watches); + } + if ((updates[i].fflags & NOTE_WRITE) && !target_file_affected) { + HandleCreateItemChange(event, &target_file_affected, &update_watches); + } + send_notification |= target_file_affected; + } + + if (update_watches) { + if (!UpdateWatches(&send_notification)) { + delegate_->OnFilePathError(target_); + Cancel(); + } + } + + if (send_notification) { + delegate_->OnFilePathChanged(target_); + } +} + +void FilePathWatcherImpl::OnFileCanWriteWithoutBlocking(int fd) { + NOTREACHED(); +} + +void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() { + CancelOnMessageLoopThread(); +} + +bool FilePathWatcherImpl::Watch(const FilePath& path, + FilePathWatcher::Delegate* delegate) { + DCHECK(MessageLoopForIO::current()); + DCHECK(target_.value().empty()); // Can only watch one path. + DCHECK(delegate); + DCHECK_EQ(kqueue_, -1); + + delegate_ = delegate; + target_ = path; + + MessageLoop::current()->AddDestructionObserver(this); + io_message_loop_ = base::MessageLoopProxy::CreateForCurrentThread(); + + kqueue_ = kqueue(); + if (kqueue_ == -1) { + PLOG(ERROR) << "kqueue"; + return false; + } + + int last_entry = EventsForPath(target_, &events_); + CHECK_NE(last_entry, 0); + + EventVector responses(last_entry); + + int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, + &responses[0], last_entry, NULL)); + if (!AreKeventValuesValid(&responses[0], count)) { + // Calling Cancel() here to close any file descriptors that were opened. + // This would happen in the destructor anyways, but FilePathWatchers tend to + // be long lived, and if an error has occurred, there is no reason to waste + // the file descriptors. + Cancel(); + return false; + } + + return MessageLoopForIO::current()->WatchFileDescriptor( + kqueue_, true, MessageLoopForIO::WATCH_READ, &kqueue_watcher_, this); +} + +void FilePathWatcherImpl::Cancel() { + base::MessageLoopProxy* proxy = io_message_loop_.get(); + if (!proxy) { + set_cancelled(); + return; + } + if (!proxy->BelongsToCurrentThread()) { + proxy->PostTask(FROM_HERE, + NewRunnableMethod(this, &FilePathWatcherImpl::Cancel)); + return; + } + CancelOnMessageLoopThread(); +} + +void FilePathWatcherImpl::CancelOnMessageLoopThread() { + DCHECK(MessageLoopForIO::current()); + if (!is_cancelled()) { + set_cancelled(); + kqueue_watcher_.StopWatchingFileDescriptor(); + CloseFileDescriptor(&kqueue_); + std::for_each(events_.begin(), events_.end(), ReleaseEvent); + events_.clear(); + io_message_loop_ = NULL; + MessageLoop::current()->RemoveDestructionObserver(this); + delegate_ = NULL; + } +} + +} // namespace + +FilePathWatcher::FilePathWatcher() { + impl_ = new FilePathWatcherImpl(); +} + +} // namespace files +} // namespace base diff --git a/base/files/file_path_watcher_stub.cc b/base/files/file_path_watcher_stub.cc new file mode 100644 index 0000000..a693dc7 --- /dev/null +++ b/base/files/file_path_watcher_stub.cc @@ -0,0 +1,31 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file exists for Unix systems which don't have the inotify headers, and +// thus cannot build file_watcher_inotify.cc + +#include "base/files/file_path_watcher.h" + +namespace base { +namespace files { + +namespace { + +class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { + public: + virtual bool Watch(const FilePath& path, + FileWatcher::Delegate* delegate, + base::MessageLoopProxy*) OVERRIDE { + return false; + } +}; + +} // namespace + +FilePathWatcher::FilePathWatcher() { + impl_ = new FilePathWatcherImpl(); +} + +} // namespace files +} // namespace base diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc new file mode 100644 index 0000000..eedcf22 --- /dev/null +++ b/base/files/file_path_watcher_win.cc @@ -0,0 +1,281 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/file_path_watcher.h" + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop_proxy.h" +#include "base/time.h" +#include "base/win/object_watcher.h" + +namespace base { +namespace files { + +namespace { + +class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate, + public base::win::ObjectWatcher::Delegate, + public MessageLoop::DestructionObserver { + public: + FilePathWatcherImpl() : delegate_(NULL), handle_(INVALID_HANDLE_VALUE) {} + + // FilePathWatcher::PlatformDelegate overrides. + virtual bool Watch(const FilePath& path, + FilePathWatcher::Delegate* delegate) OVERRIDE; + virtual void Cancel() OVERRIDE; + + // Deletion of the FilePathWatcher will call Cancel() to dispose of this + // object in the right thread. This also observes destruction of the required + // cleanup thread, in case it quits before Cancel() is called. + virtual void WillDestroyCurrentMessageLoop() OVERRIDE; + + // Callback from MessageLoopForIO. + virtual void OnObjectSignaled(HANDLE object); + + private: + virtual ~FilePathWatcherImpl() {} + + // Setup a watch handle for directory |dir|. Returns true if no fatal error + // occurs. |handle| will receive the handle value if |dir| is watchable, + // otherwise INVALID_HANDLE_VALUE. + static bool SetupWatchHandle(const FilePath& dir, HANDLE* handle) + WARN_UNUSED_RESULT; + + // (Re-)Initialize the watch handle. + bool UpdateWatch() WARN_UNUSED_RESULT; + + // Destroy the watch handle. + void DestroyWatch(); + + // Cleans up and stops observing the |message_loop_| thread. + void CancelOnMessageLoopThread() OVERRIDE; + + // Delegate to notify upon changes. + scoped_refptr<FilePathWatcher::Delegate> delegate_; + + // Path we're supposed to watch (passed to delegate). + FilePath target_; + + // Handle for FindFirstChangeNotification. + HANDLE handle_; + + // ObjectWatcher to watch handle_ for events. + base::win::ObjectWatcher watcher_; + + // Keep track of the last modified time of the file. We use nulltime + // to represent the file not existing. + base::Time last_modified_; + + // The time at which we processed the first notification with the + // |last_modified_| time stamp. + base::Time first_notification_; + + DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); +}; + +bool FilePathWatcherImpl::Watch(const FilePath& path, + FilePathWatcher::Delegate* delegate) { + DCHECK(target_.value().empty()); // Can only watch one path. + + set_message_loop(base::MessageLoopProxy::CreateForCurrentThread()); + delegate_ = delegate; + target_ = path; + MessageLoop::current()->AddDestructionObserver(this); + + if (!UpdateWatch()) + return false; + + watcher_.StartWatching(handle_, this); + + return true; +} + +void FilePathWatcherImpl::Cancel() { + if (!delegate_) { + // Watch was never called, or the |message_loop_| has already quit. + set_cancelled(); + return; + } + + // Switch to the file thread if necessary so we can stop |watcher_|. + if (!message_loop()->BelongsToCurrentThread()) { + message_loop()->PostTask(FROM_HERE, + new FilePathWatcher::CancelTask(this)); + } else { + CancelOnMessageLoopThread(); + } +} + +void FilePathWatcherImpl::CancelOnMessageLoopThread() { + set_cancelled(); + + if (handle_ != INVALID_HANDLE_VALUE) + DestroyWatch(); + + if (delegate_) { + MessageLoop::current()->RemoveDestructionObserver(this); + delegate_ = NULL; + } +} + +void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() { + CancelOnMessageLoopThread(); +} + +void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) { + DCHECK(object == handle_); + // Make sure we stay alive through the body of this function. + scoped_refptr<FilePathWatcherImpl> keep_alive(this); + + if (!UpdateWatch()) { + delegate_->OnFilePathError(target_); + return; + } + + // Check whether the event applies to |target_| and notify the delegate. + base::PlatformFileInfo file_info; + bool file_exists = file_util::GetFileInfo(target_, &file_info); + if (file_exists && (last_modified_.is_null() || + last_modified_ != file_info.last_modified)) { + last_modified_ = file_info.last_modified; + first_notification_ = base::Time::Now(); + delegate_->OnFilePathChanged(target_); + } else if (file_exists && !first_notification_.is_null()) { + // The target's last modification time is equal to what's on record. This + // means that either an unrelated event occurred, or the target changed + // again (file modification times only have a resolution of 1s). Comparing + // file modification times against the wall clock is not reliable to find + // out whether the change is recent, since this code might just run too + // late. Moreover, there's no guarantee that file modification time and wall + // clock times come from the same source. + // + // Instead, the time at which the first notification carrying the current + // |last_notified_| time stamp is recorded. Later notifications that find + // the same file modification time only need to be forwarded until wall + // clock has advanced one second from the initial notification. After that + // interval, client code is guaranteed to having seen the current revision + // of the file. + if (base::Time::Now() - first_notification_ > + base::TimeDelta::FromSeconds(1)) { + // Stop further notifications for this |last_modification_| time stamp. + first_notification_ = base::Time(); + } + delegate_->OnFilePathChanged(target_); + } else if (!file_exists && !last_modified_.is_null()) { + last_modified_ = base::Time(); + delegate_->OnFilePathChanged(target_); + } + + // The watch may have been cancelled by the callback. + if (handle_ != INVALID_HANDLE_VALUE) + watcher_.StartWatching(handle_, this); +} + +// static +bool FilePathWatcherImpl::SetupWatchHandle(const FilePath& dir, + HANDLE* handle) { + *handle = FindFirstChangeNotification( + dir.value().c_str(), + false, // Don't watch subtrees + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SECURITY); + if (*handle != INVALID_HANDLE_VALUE) { + // Make sure the handle we got points to an existing directory. It seems + // that windows sometimes hands out watches to direectories that are + // about to go away, but doesn't sent notifications if that happens. + if (!file_util::DirectoryExists(dir)) { + FindCloseChangeNotification(*handle); + *handle = INVALID_HANDLE_VALUE; + } + return true; + } + + // If FindFirstChangeNotification failed because the target directory + // doesn't exist, access is denied (happens if the file is already gone but + // there are still handles open), or the target is not a directory, try the + // immediate parent directory instead. + DWORD error_code = GetLastError(); + if (error_code != ERROR_FILE_NOT_FOUND && + error_code != ERROR_PATH_NOT_FOUND && + error_code != ERROR_ACCESS_DENIED && + error_code != ERROR_SHARING_VIOLATION && + error_code != ERROR_DIRECTORY) { + using ::operator<<; // Pick the right operator<< below. + PLOG(ERROR) << "FindFirstChangeNotification failed for " + << dir.value(); + return false; + } + + return true; +} + +bool FilePathWatcherImpl::UpdateWatch() { + if (handle_ != INVALID_HANDLE_VALUE) + DestroyWatch(); + + base::PlatformFileInfo file_info; + if (file_util::GetFileInfo(target_, &file_info)) { + last_modified_ = file_info.last_modified; + first_notification_ = base::Time::Now(); + } + + // Start at the target and walk up the directory chain until we succesfully + // create a watch handle in |handle_|. |child_dirs| keeps a stack of child + // directories stripped from target, in reverse order. + std::vector<FilePath> child_dirs; + FilePath watched_path(target_); + while (true) { + if (!SetupWatchHandle(watched_path, &handle_)) + return false; + + // Break if a valid handle is returned. Try the parent directory otherwise. + if (handle_ != INVALID_HANDLE_VALUE) + break; + + // Abort if we hit the root directory. + child_dirs.push_back(watched_path.BaseName()); + FilePath parent(watched_path.DirName()); + if (parent == watched_path) { + LOG(ERROR) << "Reached the root directory"; + return false; + } + watched_path = parent; + } + + // At this point, handle_ is valid. However, the bottom-up search that the + // above code performs races against directory creation. So try to walk back + // down and see whether any children appeared in the mean time. + while (!child_dirs.empty()) { + watched_path = watched_path.Append(child_dirs.back()); + child_dirs.pop_back(); + HANDLE temp_handle = INVALID_HANDLE_VALUE; + if (!SetupWatchHandle(watched_path, &temp_handle)) + return false; + if (temp_handle == INVALID_HANDLE_VALUE) + break; + FindCloseChangeNotification(handle_); + handle_ = temp_handle; + } + + return true; +} + +void FilePathWatcherImpl::DestroyWatch() { + watcher_.StopWatching(); + FindCloseChangeNotification(handle_); + handle_ = INVALID_HANDLE_VALUE; +} + +} // namespace + +FilePathWatcher::FilePathWatcher() { + impl_ = new FilePathWatcherImpl(); +} + +} // namespace files +} // namespace base diff --git a/base/global_descriptors_posix.h b/base/global_descriptors_posix.h index 060bf0a..d635cff 100644 --- a/base/global_descriptors_posix.h +++ b/base/global_descriptors_posix.h @@ -13,7 +13,7 @@ #include <stdint.h> -#include "base/singleton.h" +#include "base/memory/singleton.h" namespace base { diff --git a/base/hmac.h b/base/hmac.h deleted file mode 100644 index d467e1a..0000000 --- a/base/hmac.h +++ /dev/null @@ -1,60 +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. - -// Utility class for calculating the HMAC for a given message. We currently -// only support SHA1 for the hash algorithm, but this can be extended easily. - -#ifndef BASE_HMAC_H_ -#define BASE_HMAC_H_ -#pragma once - -#include <string> - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" - -namespace base { - -// Simplify the interface and reduce includes by abstracting out the internals. -struct HMACPlatformData; - -class HMAC { - public: - // The set of supported hash functions. Extend as required. - enum HashAlgorithm { - SHA1, - SHA256, - }; - - explicit HMAC(HashAlgorithm hash_alg); - ~HMAC(); - - // Initializes this instance using |key| of the length |key_length|. Call Init - // only once. It returns false on the second or later calls. - bool Init(const unsigned char* key, int key_length); - - // Initializes this instance using |key|. Call Init only once. It returns - // false on the second or later calls. - bool Init(const std::string& key) { - return Init(reinterpret_cast<const unsigned char*>(key.data()), - static_cast<int>(key.size())); - } - - // Calculates the HMAC for the message in |data| using the algorithm supplied - // to the constructor and the key supplied to the Init method. The HMAC is - // returned in |digest|, which has |digest_length| bytes of storage available. - bool Sign(const std::string& data, unsigned char* digest, int digest_length); - - // TODO(albertb): Add a Verify method. - - private: - HashAlgorithm hash_alg_; - scoped_ptr<HMACPlatformData> plat_; - - DISALLOW_COPY_AND_ASSIGN(HMAC); -}; - -} // namespace base - -#endif // BASE_HMAC_H_ diff --git a/base/hmac_mac.cc b/base/hmac_mac.cc deleted file mode 100644 index 97dcbf5..0000000 --- a/base/hmac_mac.cc +++ /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/hmac.h" - -#include <CommonCrypto/CommonHMAC.h> - -#include "base/logging.h" - -namespace base { - -struct HMACPlatformData { - std::string key_; -}; - -HMAC::HMAC(HashAlgorithm hash_alg) - : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { - // Only SHA-1 and SHA-256 hash algorithms are supported now. - DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); -} - -bool HMAC::Init(const unsigned char *key, int key_length) { - if (!plat_->key_.empty()) { - // Init must not be called more than once on the same HMAC object. - NOTREACHED(); - return false; - } - - plat_->key_.assign(reinterpret_cast<const char*>(key), key_length); - - return true; -} - -HMAC::~HMAC() { - // Zero out key copy. - plat_->key_.assign(plat_->key_.length(), std::string::value_type()); - plat_->key_.clear(); - plat_->key_.reserve(0); -} - -bool HMAC::Sign(const std::string& data, - unsigned char* digest, - int digest_length) { - CCHmacAlgorithm algorithm; - int algorithm_digest_length; - switch (hash_alg_) { - case SHA1: - algorithm = kCCHmacAlgSHA1; - algorithm_digest_length = CC_SHA1_DIGEST_LENGTH; - break; - case SHA256: - algorithm = kCCHmacAlgSHA256; - algorithm_digest_length = CC_SHA256_DIGEST_LENGTH; - break; - default: - NOTREACHED(); - return false; - } - - if (digest_length < algorithm_digest_length) { - NOTREACHED(); - return false; - } - - CCHmac(algorithm, - plat_->key_.data(), plat_->key_.length(), data.data(), data.length(), - digest); - - return true; -} - -} // namespace base diff --git a/base/hmac_nss.cc b/base/hmac_nss.cc deleted file mode 100644 index af0b3eb..0000000 --- a/base/hmac_nss.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/hmac.h" - -#include <nss.h> -#include <pk11pub.h> - -#include "base/crypto/scoped_nss_types.h" -#include "base/logging.h" -#include "base/nss_util.h" -#include "base/scoped_ptr.h" - -namespace base { - -struct HMACPlatformData { - CK_MECHANISM_TYPE mechanism_; - ScopedPK11Slot slot_; - ScopedPK11SymKey sym_key_; -}; - -HMAC::HMAC(HashAlgorithm hash_alg) - : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { - // Only SHA-1 and SHA-256 hash algorithms are supported. - switch (hash_alg_) { - case SHA1: - plat_->mechanism_ = CKM_SHA_1_HMAC; - break; - case SHA256: - plat_->mechanism_ = CKM_SHA256_HMAC; - break; - default: - NOTREACHED() << "Unsupported hash algorithm"; - break; - } -} - -HMAC::~HMAC() { -} - -bool HMAC::Init(const unsigned char *key, int key_length) { - base::EnsureNSSInit(); - - if (plat_->slot_.get()) { - // Init must not be called more than twice on the same HMAC object. - NOTREACHED(); - return false; - } - - plat_->slot_.reset(PK11_GetBestSlot(plat_->mechanism_, NULL)); - if (!plat_->slot_.get()) { - NOTREACHED(); - return false; - } - - SECItem key_item; - key_item.type = siBuffer; - key_item.data = const_cast<unsigned char*>(key); // NSS API isn't const. - key_item.len = key_length; - - plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(), - plat_->mechanism_, - PK11_OriginUnwrap, - CKA_SIGN, - &key_item, - NULL)); - if (!plat_->sym_key_.get()) { - NOTREACHED(); - return false; - } - - return true; -} - -bool HMAC::Sign(const std::string& data, - unsigned char* digest, - int digest_length) { - if (!plat_->sym_key_.get()) { - // Init has not been called before Sign. - NOTREACHED(); - return false; - } - - SECItem param = { siBuffer, NULL, 0 }; - ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_, - CKA_SIGN, - plat_->sym_key_.get(), - ¶m)); - if (!context.get()) { - NOTREACHED(); - return false; - } - - if (PK11_DigestBegin(context.get()) != SECSuccess) { - NOTREACHED(); - return false; - } - - if (PK11_DigestOp(context.get(), - reinterpret_cast<const unsigned char*>(data.data()), - data.length()) != SECSuccess) { - NOTREACHED(); - return false; - } - - unsigned int len = 0; - if (PK11_DigestFinal(context.get(), - digest, &len, digest_length) != SECSuccess) { - NOTREACHED(); - return false; - } - - return true; -} - -} // namespace base diff --git a/base/hmac_openssl.cc b/base/hmac_openssl.cc deleted file mode 100644 index f45d3a7..0000000 --- a/base/hmac_openssl.cc +++ /dev/null @@ -1,57 +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/hmac.h" - -#include <openssl/hmac.h> - -#include <algorithm> -#include <vector> - -#include "base/logging.h" -#include "base/openssl_util.h" -#include "base/scoped_ptr.h" -#include "base/stl_util-inl.h" - -namespace base { - -struct HMACPlatformData { - std::vector<unsigned char> key; -}; - -HMAC::HMAC(HashAlgorithm hash_alg) - : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { - // Only SHA-1 and SHA-256 hash algorithms are supported now. - DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); -} - -bool HMAC::Init(const unsigned char* key, int key_length) { - // Init must not be called more than once on the same HMAC object. - DCHECK(plat_->key.empty()); - - plat_->key.assign(key, key + key_length); - return true; -} - -HMAC::~HMAC() { - // Zero out key copy. - plat_->key.assign(plat_->key.size(), 0); - STLClearObject(&plat_->key); -} - -bool HMAC::Sign(const std::string& data, - unsigned char* digest, - int digest_length) { - DCHECK_GE(digest_length, 0); - DCHECK(!plat_->key.empty()); // Init must be called before Sign. - - ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> result(digest, digest_length); - return ::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), - &plat_->key[0], plat_->key.size(), - reinterpret_cast<const unsigned char*>(data.data()), - data.size(), - result.safe_buffer(), NULL); -} - -} // namespace base diff --git a/base/hmac_unittest.cc b/base/hmac_unittest.cc deleted file mode 100644 index 480c771..0000000 --- a/base/hmac_unittest.cc +++ /dev/null @@ -1,236 +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 <string> - -#include "base/hmac.h" -#include "testing/gtest/include/gtest/gtest.h" - -static const int kSHA1DigestSize = 20; -static const int kSHA256DigestSize = 32; - -TEST(HMACTest, HmacSafeBrowsingResponseTest) { - const int kKeySize = 16; - - // Client key. - const unsigned char kClientKey[kKeySize] = - { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd, - 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 }; - - // Expected HMAC result using kMessage and kClientKey. - const unsigned char kReceivedHmac[kSHA1DigestSize] = - { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52, - 0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad, - 0x86, 0xd2, 0x48, 0x85 }; - - const char kMessage[] = -"n:1896\ni:goog-malware-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav" -"ar_s_445-450\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_439-444\nu:s" -".ytimg.com/safebrowsing/rd/goog-malware-shavar_s_437\nu:s.ytimg.com/safebrowsi" -"ng/rd/goog-malware-shavar_s_436\nu:s.ytimg.com/safebrowsing/rd/goog-malware-sh" -"avar_s_433-435\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_431\nu:s.y" -"timg.com/safebrowsing/rd/goog-malware-shavar_s_430\nu:s.ytimg.com/safebrowsing" -"/rd/goog-malware-shavar_s_429\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav" -"ar_s_428\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_426\nu:s.ytimg.c" -"om/safebrowsing/rd/goog-malware-shavar_s_424\nu:s.ytimg.com/safebrowsing/rd/go" -"og-malware-shavar_s_423\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4" -"22\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_420\nu:s.ytimg.com/saf" -"ebrowsing/rd/goog-malware-shavar_s_419\nu:s.ytimg.com/safebrowsing/rd/goog-mal" -"ware-shavar_s_414\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_409-411" -"\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_405\nu:s.ytimg.com/safeb" -"rowsing/rd/goog-malware-shavar_s_404\nu:s.ytimg.com/safebrowsing/rd/goog-malwa" -"re-shavar_s_402\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_401\nu:s." -"ytimg.com/safebrowsing/rd/goog-malware-shavar_a_973-978\nu:s.ytimg.com/safebro" -"wsing/rd/goog-malware-shavar_a_937-972\nu:s.ytimg.com/safebrowsing/rd/goog-mal" -"ware-shavar_a_931-936\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_925" -"-930\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_919-924\ni:goog-phis" -"h-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2633\nu:s.ytimg.co" -"m/safebrowsing/rd/goog-phish-shavar_a_2632\nu:s.ytimg.com/safebrowsing/rd/goog" -"-phish-shavar_a_2629-2631\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2" -"626-2628\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2625\n"; - - std::string message_data(kMessage); - - base::HMAC hmac(base::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(kClientKey, kKeySize)); - unsigned char calculated_hmac[kSHA1DigestSize]; - - EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize)); -} - -// Test cases from RFC 2202 section 3 -TEST(HMACTest, RFC2202TestCases) { - const struct { - const char *key; - const int key_len; - const char *data; - const int data_len; - const char *digest; - } cases[] = { - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" - "\x0B\x0B\x0B\x0B", 20, - "Hi There", 8, - "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E" - "\xF1\x46\xBE\x00" }, - { "Jefe", 4, - "what do ya want for nothing?", 28, - "\xEF\xFC\xDF\x6A\xE5\xEB\x2F\xA2\xD2\x74\x16\xD5\xF1\x84\xDF\x9C" - "\x25\x9A\x7C\x79" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA", 20, - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD", 50, - "\x12\x5D\x73\x42\xB9\xAC\x11\xCD\x91\xA3\x9A\xF4\x8A\xA1\x7B\x4F" - "\x63\xF1\x75\xD3" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25, - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD", 50, - "\x4C\x90\x07\xF4\x02\x62\x50\xC6\xBC\x84\x14\xF9\xBF\x50\xC8\x6C" - "\x2D\x72\x35\xDA" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" - "\x0C\x0C\x0C\x0C", 20, - "Test With Truncation", 20, - "\x4C\x1A\x03\x42\x4B\x55\xE0\x7F\xE7\xF2\x7B\xE1\xD5\x8B\xB9\x32" - "\x4A\x9A\x5A\x04" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", - 80, - "Test Using Larger Than Block-Size Key - Hash Key First", 54, - "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55" - "\xED\x40\x21\x12" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", - 80, - "Test Using Larger Than Block-Size Key and Larger " - "Than One Block-Size Data", 73, - "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08" - "\xBB\xFF\x1A\x91" } - }; - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { - base::HMAC hmac(base::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(reinterpret_cast<const unsigned char*>(cases[i].key), - cases[i].key_len)); - std::string data_string(cases[i].data, cases[i].data_len); - unsigned char digest[kSHA1DigestSize]; - EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize)); - } -} - -// TODO(wtc): add other test vectors from RFC 4231. -TEST(HMACTest, RFC4231TestCase6) { - unsigned char key[131]; - for (size_t i = 0; i < sizeof(key); ++i) - key[i] = 0xaa; - - std::string data = "Test Using Larger Than Block-Size Key - Hash Key First"; - ASSERT_EQ(54U, data.size()); - - static unsigned char kKnownHMACSHA256[] = { - 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, - 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, - 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, - 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 - }; - - base::HMAC hmac(base::HMAC::SHA256); - ASSERT_TRUE(hmac.Init(key, sizeof(key))); - unsigned char calculated_hmac[kSHA256DigestSize]; - - EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize)); - EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize)); -} - -// Based on NSS's FIPS HMAC power-up self-test. -TEST(HMACTest, NSSFIPSPowerUpSelfTest) { - static const char kKnownMessage[] = - "The test message for the MD2, MD5, and SHA-1 hashing algorithms."; - - static const unsigned char kKnownSecretKey[] = { - 0x46, 0x69, 0x72, 0x65, 0x66, 0x6f, 0x78, 0x20, - 0x61, 0x6e, 0x64, 0x20, 0x54, 0x68, 0x75, 0x6e, - 0x64, 0x65, 0x72, 0x42, 0x69, 0x72, 0x64, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x61, 0x77, 0x65, 0x73, - 0x6f, 0x6d, 0x65, 0x21, 0x00 - }; - - static const size_t kKnownSecretKeySize = sizeof(kKnownSecretKey); - - // HMAC-SHA-1 known answer (20 bytes). - static const unsigned char kKnownHMACSHA1[] = { - 0xd5, 0x85, 0xf6, 0x5b, 0x39, 0xfa, 0xb9, 0x05, - 0x3b, 0x57, 0x1d, 0x61, 0xe7, 0xb8, 0x84, 0x1e, - 0x5d, 0x0e, 0x1e, 0x11 - }; - - // HMAC-SHA-256 known answer (32 bytes). - static const unsigned char kKnownHMACSHA256[] = { - 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44, - 0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14, 0x22, 0xe0, - 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9, - 0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48 - }; - - std::string message_data(kKnownMessage); - - base::HMAC hmac(base::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(kKnownSecretKey, kKnownSecretKeySize)); - unsigned char calculated_hmac[kSHA1DigestSize]; - - EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize)); - - base::HMAC hmac2(base::HMAC::SHA256); - ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize)); - unsigned char calculated_hmac2[kSHA256DigestSize]; - - EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize)); - EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize)); -} - -TEST(HMACTest, HMACObjectReuse) { - const char *key = - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; - const int key_len = 80; - - const struct { - const char *data; - const int data_len; - const char *digest; - } cases[] = { - { "Test Using Larger Than Block-Size Key - Hash Key First", 54, - "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55" - "\xED\x40\x21\x12" }, - { "Test Using Larger Than Block-Size Key and Larger " - "Than One Block-Size Data", 73, - "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08" - "\xBB\xFF\x1A\x91" } - }; - - base::HMAC hmac(base::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(reinterpret_cast<const unsigned char*>(key), key_len)); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { - std::string data_string(cases[i].data, cases[i].data_len); - unsigned char digest[kSHA1DigestSize]; - EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize)); - } -} diff --git a/base/hmac_win.cc b/base/hmac_win.cc deleted file mode 100644 index a1c8225..0000000 --- a/base/hmac_win.cc +++ /dev/null @@ -1,197 +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/hmac.h" - -#include <windows.h> -#include <wincrypt.h> - -#include <algorithm> -#include <vector> - -#include "base/crypto/scoped_capi_types.h" -#include "base/logging.h" -#include "base/third_party/nss/blapi.h" -#include "base/third_party/nss/sha256.h" - -namespace base { - -namespace { - -// Implementation of HMAC-SHA-256: -// -// SHA-256 is supported in Windows XP SP3 or later. We still need to support -// Windows XP SP2, so unfortunately we have to implement HMAC-SHA-256 here. - -enum { - SHA256_BLOCK_SIZE = 64 // Block size (in bytes) of the input to SHA-256. -}; - -// See FIPS 198: The Keyed-Hash Message Authentication Code (HMAC). -void ComputeHMACSHA256(const unsigned char* key, size_t key_len, - const unsigned char* text, size_t text_len, - unsigned char* output, size_t output_len) { - SHA256Context ctx; - - // Pre-process the key, if necessary. - unsigned char key0[SHA256_BLOCK_SIZE]; - if (key_len > SHA256_BLOCK_SIZE) { - SHA256_Begin(&ctx); - SHA256_Update(&ctx, key, key_len); - SHA256_End(&ctx, key0, NULL, SHA256_LENGTH); - memset(key0 + SHA256_LENGTH, 0, SHA256_BLOCK_SIZE - SHA256_LENGTH); - } else { - memcpy(key0, key, key_len); - memset(key0 + key_len, 0, SHA256_BLOCK_SIZE - key_len); - } - - unsigned char padded_key[SHA256_BLOCK_SIZE]; - unsigned char inner_hash[SHA256_LENGTH]; - - // XOR key0 with ipad. - for (int i = 0; i < SHA256_BLOCK_SIZE; ++i) - padded_key[i] = key0[i] ^ 0x36; - - // Compute the inner hash. - SHA256_Begin(&ctx); - SHA256_Update(&ctx, padded_key, SHA256_BLOCK_SIZE); - SHA256_Update(&ctx, text, text_len); - SHA256_End(&ctx, inner_hash, NULL, SHA256_LENGTH); - - // XOR key0 with opad. - for (int i = 0; i < SHA256_BLOCK_SIZE; ++i) - padded_key[i] = key0[i] ^ 0x5c; - - // Compute the outer hash. - SHA256_Begin(&ctx); - SHA256_Update(&ctx, padded_key, SHA256_BLOCK_SIZE); - SHA256_Update(&ctx, inner_hash, SHA256_LENGTH); - SHA256_End(&ctx, output, NULL, output_len); -} - -} // namespace - -struct HMACPlatformData { - ~HMACPlatformData() { - if (!raw_key_.empty()) { - SecureZeroMemory(&raw_key_[0], raw_key_.size()); - } - - // Destroy the key before releasing the provider. - key_.reset(); - } - - ScopedHCRYPTPROV provider_; - ScopedHCRYPTKEY key_; - - // For HMAC-SHA-256 only. - std::vector<unsigned char> raw_key_; -}; - -HMAC::HMAC(HashAlgorithm hash_alg) - : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { - // Only SHA-1 and SHA-256 hash algorithms are supported now. - DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); -} - -bool HMAC::Init(const unsigned char* key, int key_length) { - if (plat_->provider_ || plat_->key_ || !plat_->raw_key_.empty()) { - // Init must not be called more than once on the same HMAC object. - NOTREACHED(); - return false; - } - - if (hash_alg_ == SHA256) { - if (key_length < SHA256_LENGTH / 2) - return false; // Key is too short. - plat_->raw_key_.assign(key, key + key_length); - return true; - } - - if (!CryptAcquireContext(plat_->provider_.receive(), NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - NOTREACHED(); - return false; - } - - // This code doesn't work on Win2k because PLAINTEXTKEYBLOB and - // CRYPT_IPSEC_HMAC_KEY are not supported on Windows 2000. PLAINTEXTKEYBLOB - // allows the import of an unencrypted key. For Win2k support, a cubmbersome - // exponent-of-one key procedure must be used: - // http://support.microsoft.com/kb/228786/en-us - // CRYPT_IPSEC_HMAC_KEY allows keys longer than 16 bytes. - - struct KeyBlob { - BLOBHEADER header; - DWORD key_size; - BYTE key_data[1]; - }; - size_t key_blob_size = std::max(offsetof(KeyBlob, key_data) + key_length, - sizeof(KeyBlob)); - std::vector<BYTE> key_blob_storage = std::vector<BYTE>(key_blob_size); - KeyBlob* key_blob = reinterpret_cast<KeyBlob*>(&key_blob_storage[0]); - key_blob->header.bType = PLAINTEXTKEYBLOB; - key_blob->header.bVersion = CUR_BLOB_VERSION; - key_blob->header.reserved = 0; - key_blob->header.aiKeyAlg = CALG_RC2; - key_blob->key_size = key_length; - memcpy(key_blob->key_data, key, key_length); - - if (!CryptImportKey(plat_->provider_, &key_blob_storage[0], - key_blob_storage.size(), 0, CRYPT_IPSEC_HMAC_KEY, - plat_->key_.receive())) { - NOTREACHED(); - return false; - } - - // Destroy the copy of the key. - SecureZeroMemory(key_blob->key_data, key_length); - - return true; -} - -HMAC::~HMAC() { -} - -bool HMAC::Sign(const std::string& data, - unsigned char* digest, - int digest_length) { - if (hash_alg_ == SHA256) { - if (plat_->raw_key_.empty()) - return false; - ComputeHMACSHA256(&plat_->raw_key_[0], plat_->raw_key_.size(), - reinterpret_cast<const unsigned char*>(data.data()), - data.size(), digest, digest_length); - return true; - } - - if (!plat_->provider_ || !plat_->key_) - return false; - - if (hash_alg_ != SHA1) { - NOTREACHED(); - return false; - } - - ScopedHCRYPTHASH hash; - if (!CryptCreateHash(plat_->provider_, CALG_HMAC, plat_->key_, 0, - hash.receive())) - return false; - - HMAC_INFO hmac_info; - memset(&hmac_info, 0, sizeof(hmac_info)); - hmac_info.HashAlgid = CALG_SHA1; - if (!CryptSetHashParam(hash, HP_HMAC_INFO, - reinterpret_cast<BYTE*>(&hmac_info), 0)) - return false; - - if (!CryptHashData(hash, reinterpret_cast<const BYTE*>(data.data()), - static_cast<DWORD>(data.size()), 0)) - return false; - - DWORD sha1_size = digest_length; - return !!CryptGetHashParam(hash, HP_HASHVAL, digest, &sha1_size, 0); -} - -} // namespace base diff --git a/base/i18n/break_iterator.cc b/base/i18n/break_iterator.cc index e1b5e29..edc8950 100644 --- a/base/i18n/break_iterator.cc +++ b/base/i18n/break_iterator.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -33,7 +33,7 @@ bool BreakIterator::Init() { case BREAK_WORD: break_type = UBRK_WORD; break; - case BREAK_SPACE: + case BREAK_LINE: case BREAK_NEWLINE: break_type = UBRK_LINE; break; @@ -59,7 +59,7 @@ bool BreakIterator::Advance() { prev_ = pos_; switch (break_type_) { case BREAK_WORD: - case BREAK_SPACE: + case BREAK_LINE: pos = ubrk_next(static_cast<UBreakIterator*>(iter_)); if (pos == UBRK_DONE) { pos_ = npos; diff --git a/base/i18n/break_iterator.h b/base/i18n/break_iterator.h index 9de7ac7..f64a1e1 100644 --- a/base/i18n/break_iterator.h +++ b/base/i18n/break_iterator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,19 +12,28 @@ // 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, +// It provides several modes, BREAK_WORD, BREAK_LINE, 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.!. ."). +// Note that Chinese/Japanese/Thai do not use spaces between words so that +// boundaries can fall in the middle of a continuous run of non-space / +// non-punctuation characters. // -// 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_LINE mode, once a line breaking opportunity is encountered, +// any non-word characters are included in the returned string, breaking +// only when a space-equivalent character or a line breaking opportunity +// is encountered (e.g. in the UTF16-equivalent of the string " foo bar! ", +// the breaks are at the periods in ". .foo .bar! ."). +// +// Note that lines can be broken at any character/syllable/grapheme cluster +// boundary in Chinese/Japanese/Korean and at word boundaries in Thai +// (Thai does not use spaces between words). Therefore, this is NOT the same +// as breaking only at space-equivalent characters where its former +// name (BREAK_SPACE) implied. // // Under BREAK_NEWLINE mode, all characters are included in the returned // string, breking only when a newline-equivalent character is encountered @@ -48,7 +57,11 @@ class BreakIterator { public: enum BreakType { BREAK_WORD, - BREAK_SPACE, + BREAK_LINE, + // TODO(jshin): Remove this after reviewing call sites. + // If call sites really need break only on space-like characters + // implement it separately. + BREAK_SPACE = BREAK_LINE, BREAK_NEWLINE, }; @@ -75,7 +88,7 @@ class BreakIterator { // 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, + // whitespace or punctuation.) Under BREAK_LINE and BREAK_NEWLINE modes, // this distinction doesn't apply and it always retuns false. bool IsWord() const; diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc index ba69da0..9d12097 100644 --- a/base/i18n/file_util_icu.cc +++ b/base/i18n/file_util_icu.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,8 +8,8 @@ #include "base/file_path.h" #include "base/logging.h" -#include "base/scoped_ptr.h" -#include "base/singleton.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/sys_string_conversions.h" diff --git a/base/i18n/file_util_icu_unittest.cc b/base/i18n/file_util_icu_unittest.cc index 1da8a93..6c5d34d 100644 --- a/base/i18n/file_util_icu_unittest.cc +++ b/base/i18n/file_util_icu_unittest.cc @@ -1,11 +1,10 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/i18n/file_util_icu.h" #include "base/file_util.h" -#include "base/path_service.h" #include "base/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -13,26 +12,6 @@ // file_util winds up using autoreleased objects on the Mac, so this needs // to be a PlatformTest class FileUtilICUTest : public PlatformTest { - protected: - virtual void SetUp() { - PlatformTest::SetUp(); - // Name a subdirectory of the temp directory. - ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_)); - test_dir_ = test_dir_.Append(FILE_PATH_LITERAL("FileUtilTest")); - - // Create a fresh, empty copy of this directory. - file_util::Delete(test_dir_, true); - file_util::CreateDirectory(test_dir_); - } - virtual void TearDown() { - PlatformTest::TearDown(); - // Clean up test directory - ASSERT_TRUE(file_util::Delete(test_dir_, true)); - ASSERT_FALSE(file_util::PathExists(test_dir_)); - } - - // the path to temporary directory used to contain the test operations - FilePath test_dir_; }; #if defined(OS_POSIX) && !defined(OS_MACOSX) diff --git a/base/i18n/icu_encoding_detection.cc b/base/i18n/icu_encoding_detection.cc index d579af2..2081c7a 100644 --- a/base/i18n/icu_encoding_detection.cc +++ b/base/i18n/icu_encoding_detection.cc @@ -1,9 +1,11 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/i18n/icu_encoding_detection.h" +#include <set> + #include "base/string_util.h" #include "unicode/ucsdet.h" @@ -20,6 +22,8 @@ bool DetectEncoding(const std::string& text, std::string* encoding) { ucsdet_setText(detector, text.data(), static_cast<int32_t>(text.length()), &status); const UCharsetMatch* match = ucsdet_detect(detector, &status); + if (match == NULL) + return false; const char* detected_encoding = ucsdet_getName(match, &status); ucsdet_close(detector); @@ -45,6 +49,13 @@ bool DetectAllEncodings(const std::string& text, return false; } + // ICU has some heuristics for encoding detection, such that the more likely + // encodings should be returned first. However, it doesn't always return + // all encodings that properly decode |text|, so we'll append more encodings + // later. To make that efficient, keep track of encodings sniffed in this + // first phase. + std::set<std::string> sniffed_encodings; + encodings->clear(); for (int i = 0; i < matches_count; i++) { UErrorCode get_name_status = U_ZERO_ERROR; @@ -54,8 +65,37 @@ bool DetectAllEncodings(const std::string& text, if (U_FAILURE(get_name_status)) continue; + int32_t confidence = ucsdet_getConfidence(matches[i], &get_name_status); + + // We also treat this error as non-fatal. + if (U_FAILURE(get_name_status)) + continue; + + // A confidence level >= 10 means that the encoding is expected to properly + // decode the text. Drop all encodings with lower confidence level. + if (confidence < 10) + continue; + encodings->push_back(encoding_name); + sniffed_encodings.insert(encoding_name); + } + + // Append all encodings not included earlier, in arbitrary order. + // TODO(jshin): This shouldn't be necessary, possible ICU bug. + // See also http://crbug.com/65917. + UEnumeration* detectable_encodings = ucsdet_getAllDetectableCharsets(detector, + &status); + int detectable_count = uenum_count(detectable_encodings, &status); + for (int i = 0; i < detectable_count; i++) { + int name_length; + const char* name_raw = uenum_next(detectable_encodings, + &name_length, + &status); + std::string name(name_raw, name_length); + if (sniffed_encodings.find(name) == sniffed_encodings.end()) + encodings->push_back(name); } + uenum_close(detectable_encodings); ucsdet_close(detector); return !encodings->empty(); diff --git a/base/i18n/icu_encoding_detection.h b/base/i18n/icu_encoding_detection.h index cdc4cb7..06c2567 100644 --- a/base/i18n/icu_encoding_detection.h +++ b/base/i18n/icu_encoding_detection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -18,6 +18,8 @@ bool DetectEncoding(const std::string& text, std::string* encoding); // Detect all possible encodings of |text| and put their names // (as returned by ICU) in |encodings|. Returns true on success. +// Note: this function may return encodings that may fail to decode |text|, +// the caller is responsible for handling that. bool DetectAllEncodings(const std::string& text, std::vector<std::string>* encodings); diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc index eb7a688..4f17f17 100644 --- a/base/i18n/icu_util.cc +++ b/base/i18n/icu_util.cc @@ -44,7 +44,7 @@ #elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED #define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat" #if defined(OS_WIN) -#define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt" U_ICU_VERSION_SHORT ".dll" +#define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt.dll" #endif #endif diff --git a/base/i18n/number_formatting.cc b/base/i18n/number_formatting.cc index df6af14..6b28de5 100644 --- a/base/i18n/number_formatting.cc +++ b/base/i18n/number_formatting.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,7 +7,7 @@ #include "base/format_macros.h" #include "base/logging.h" #include "base/lazy_instance.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "unicode/numfmt.h" diff --git a/base/i18n/rtl_unittest.cc b/base/i18n/rtl_unittest.cc index 061e140..3ee8254 100644 --- a/base/i18n/rtl_unittest.cc +++ b/base/i18n/rtl_unittest.cc @@ -4,9 +4,12 @@ #include "base/i18n/rtl.h" +#include <algorithm> + #include "base/file_path.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" +#include "base/sys_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -115,88 +118,53 @@ TEST_F(RTLTest, GetFirstStrongCharacterDirection) { base::i18n::GetFirstStrongCharacterDirection(string)); } -typedef struct { - std::wstring path; - std::wstring wrapped_path; -} PathAndWrappedPath; - TEST_F(RTLTest, WrapPathWithLTRFormatting) { - std::wstring kSeparator; - kSeparator.push_back(static_cast<wchar_t>(FilePath::kSeparators[0])); - const PathAndWrappedPath test_data[] = { + const wchar_t* kTestData[] = { // Test common path, such as "c:\foo\bar". - { L"c:" + kSeparator + L"foo" + kSeparator + L"bar", - L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + - L"bar\x202c" - }, + L"c:/foo/bar", // Test path with file name, such as "c:\foo\bar\test.jpg". - { L"c:" + kSeparator + L"foo" + kSeparator + L"bar" + kSeparator + - L"test.jpg", - L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + - L"bar" + kSeparator + L"test.jpg\x202c" - }, + L"c:/foo/bar/test.jpg", // Test path ending with punctuation, such as "c:\(foo)\bar.". - { L"c:" + kSeparator + L"(foo)" + kSeparator + L"bar.", - L"\x202a"L"c:" + kSeparator + L"(foo)" + kSeparator + - L"bar.\x202c" - }, + L"c:/(foo)/bar.", // Test path ending with separator, such as "c:\foo\bar\". - { L"c:" + kSeparator + L"foo" + kSeparator + L"bar" + kSeparator, - L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + - L"bar" + kSeparator + L"\x202c", - }, + L"c:/foo/bar/", // Test path with RTL character. - { L"c:" + kSeparator + L"\x05d0", - L"\x202a"L"c:" + kSeparator + L"\x05d0\x202c", - }, + L"c:/\x05d0", // Test path with 2 level RTL directory names. - { L"c:" + kSeparator + L"\x05d0" + kSeparator + L"\x0622", - L"\x202a"L"c:" + kSeparator + L"\x05d0" + kSeparator + - L"\x0622\x202c", - }, + L"c:/\x05d0/\x0622", // Test path with mixed RTL/LTR directory names and ending with punctuation. - { L"c:" + kSeparator + L"\x05d0" + kSeparator + L"\x0622" + kSeparator + - L"(foo)" + kSeparator + L"b.a.r.", - L"\x202a"L"c:" + kSeparator + L"\x05d0" + kSeparator + - L"\x0622" + kSeparator + L"(foo)" + kSeparator + - L"b.a.r.\x202c", - }, + L"c:/\x05d0/\x0622/(foo)/b.a.r.", // Test path without driver name, such as "/foo/bar/test/jpg". - { kSeparator + L"foo" + kSeparator + L"bar" + kSeparator + L"test.jpg", - L"\x202a" + kSeparator + L"foo" + kSeparator + L"bar" + - kSeparator + L"test.jpg" + L"\x202c" - }, + L"/foo/bar/test.jpg", // Test path start with current directory, such as "./foo". - { L"." + kSeparator + L"foo", - L"\x202a"L"." + kSeparator + L"foo" + L"\x202c" - }, + L"./foo", // Test path start with parent directory, such as "../foo/bar.jpg". - { L".." + kSeparator + L"foo" + kSeparator + L"bar.jpg", - L"\x202a"L".." + kSeparator + L"foo" + kSeparator + - L"bar.jpg" + L"\x202c" - }, + L"../foo/bar.jpg", // Test absolute path, such as "//foo/bar.jpg". - { kSeparator + kSeparator + L"foo" + kSeparator + L"bar.jpg", - L"\x202a" + kSeparator + kSeparator + L"foo" + kSeparator + - L"bar.jpg" + L"\x202c" - }, + L"//foo/bar.jpg", // Test path with mixed RTL/LTR directory names. - { L"c:" + kSeparator + L"foo" + kSeparator + L"\x05d0" + kSeparator + - L"\x0622" + kSeparator + L"\x05d1.jpg", - L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + L"\x05d0" + - kSeparator + L"\x0622" + kSeparator + L"\x05d1.jpg" + L"\x202c", - }, + L"c:/foo/\x05d0/\x0622/\x05d1.jpg", // Test empty path. - { L"", - L"\x202a\x202c" - } + L"" }; - for (unsigned int i = 0; i < arraysize(test_data); ++i) { + for (unsigned int i = 0; i < arraysize(kTestData); ++i) { + FilePath path; +#if defined(OS_WIN) + std::wstring win_path(kTestData[i]); + std::replace(win_path.begin(), win_path.end(), '/', '\\'); + path = FilePath(win_path); + std::wstring wrapped_expected = + std::wstring(L"\x202a") + win_path + L"\x202c"; +#else + path = FilePath(base::SysWideToNativeMB(kTestData[i])); + std::wstring wrapped_expected = + std::wstring(L"\x202a") + kTestData[i] + L"\x202c"; +#endif string16 localized_file_path_string; - FilePath path = FilePath::FromWStringHack(test_data[i].path); base::i18n::WrapPathWithLTRFormatting(path, &localized_file_path_string); - std::wstring wrapped_path = UTF16ToWide(localized_file_path_string); - EXPECT_EQ(wrapped_path, test_data[i].wrapped_path); + + std::wstring wrapped_actual = UTF16ToWide(localized_file_path_string); + EXPECT_EQ(wrapped_expected, wrapped_actual); } } diff --git a/base/i18n/time_formatting.cc b/base/i18n/time_formatting.cc index 3fa984a..e52bd22 100644 --- a/base/i18n/time_formatting.cc +++ b/base/i18n/time_formatting.cc @@ -1,14 +1,16 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/i18n/time_formatting.h" #include "base/logging.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/utf_string_conversions.h" #include "base/time.h" #include "unicode/datefmt.h" +#include "unicode/dtptngen.h" +#include "unicode/smpdtfmt.h" using base::Time; @@ -36,6 +38,34 @@ string16 TimeFormatTimeOfDay(const Time& time) { return TimeFormat(formatter.get(), time); } +string16 TimeFormatTimeOfDayWithHourClockType(const Time& time, + HourClockType type) { + // Just redirect to the normal function if the default type matches the + // given type. + HourClockType default_type = GetHourClockType(); + if (default_type == type) { + return TimeFormatTimeOfDay(time); + } + + // Generate a locale-dependent format pattern. The generator will take + // care of locale-dependent formatting issues like which separator to + // use (some locales use '.' instead of ':'), and where to put the am/pm + // marker. + UErrorCode status = U_ZERO_ERROR; + icu::DateTimePatternGenerator *generator = + icu::DateTimePatternGenerator::createInstance(status); + CHECK(U_SUCCESS(status)); + const char* base_pattern = (type == k12HourClock ? "ahm" : "Hm"); + icu::UnicodeString generated_pattern = + generator->getBestPattern(icu::UnicodeString(base_pattern), status); + CHECK(U_SUCCESS(status)); + + // Then, format the time using the generated pattern. + icu::SimpleDateFormat formatter(generated_pattern, status); + CHECK(U_SUCCESS(status)); + return TimeFormat(&formatter, time); +} + string16 TimeFormatShortDate(const Time& time) { scoped_ptr<icu::DateFormat> formatter( icu::DateFormat::createDateInstance(icu::DateFormat::kMedium)); @@ -66,4 +96,44 @@ string16 TimeFormatFriendlyDate(const Time& time) { return TimeFormat(formatter.get(), time); } +HourClockType GetHourClockType() { + // TODO(satorux,jshin): Rework this with ures_getByKeyWithFallback() + // once it becomes public. The short time format can be found at + // "calendar/gregorian/DateTimePatterns/3" in the resources. + scoped_ptr<icu::SimpleDateFormat> formatter( + static_cast<icu::SimpleDateFormat*>( + icu::DateFormat::createTimeInstance(icu::DateFormat::kShort))); + // Retrieve the short time format. + icu::UnicodeString pattern_unicode; + formatter->toPattern(pattern_unicode); + + // Determine what hour clock type the current locale uses, by checking + // "a" (am/pm marker) in the short time format. This is reliable as "a" + // is used by all of 12-hour clock formats, but not any of 24-hour clock + // formats, as shown below. + // + // % grep -A4 DateTimePatterns third_party/icu/source/data/locales/*.txt | + // grep -B1 -- -- |grep -v -- '--' | + // perl -nle 'print $1 if /^\S+\s+"(.*)"/' |sort -u + // + // H.mm + // H:mm + // HH.mm + // HH:mm + // a h:mm + // ah:mm + // ahh:mm + // h-mm a + // h:mm a + // hh:mm a + // + // See http://userguide.icu-project.org/formatparse/datetime for details + // about the date/time format syntax. + if (pattern_unicode.indexOf('a') == -1) { + return k24HourClock; + } else { + return k12HourClock; + } +} + } // namespace base diff --git a/base/i18n/time_formatting.h b/base/i18n/time_formatting.h index e70ad3d..99d1911 100644 --- a/base/i18n/time_formatting.h +++ b/base/i18n/time_formatting.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -15,9 +15,21 @@ namespace base { class Time; +// Argument type used to specify the hour clock type. +enum HourClockType { + k12HourClock, // Uses 1-12. e.g., "3:07 PM" + k24HourClock, // Uses 0-23. e.g., "15:07" +}; + // Returns the time of day, e.g., "3:07 PM". string16 TimeFormatTimeOfDay(const Time& time); +// Returns the time of day in the specified hour clock type. e.g. +// "3:07 PM" (type == k12HourClock). +// "15:07" (type == k24HourClock). +string16 TimeFormatTimeOfDayWithHourClockType(const Time& time, + HourClockType type); + // Returns a shortened date, e.g. "Nov 7, 2007" string16 TimeFormatShortDate(const Time& time); @@ -36,6 +48,11 @@ string16 TimeFormatFriendlyDateAndTime(const Time& time); // "Monday, March 6, 2008". string16 TimeFormatFriendlyDate(const Time& time); +// Gets the hour clock type of the current locale. e.g. +// k12HourClock (en-US). +// k24HourClock (en-GB). +HourClockType GetHourClockType(); + } // namespace base #endif // BASE_I18N_TIME_FORMATTING_H_ diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc index c8fe78d..82bc7d4 100644 --- a/base/json/json_reader.cc +++ b/base/json/json_reader.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,7 @@ #include "base/float_util.h" #include "base/logging.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" diff --git a/base/json/json_reader.h b/base/json/json_reader.h index a6f0686..4f83492 100644 --- a/base/json/json_reader.h +++ b/base/json/json_reader.h @@ -34,6 +34,7 @@ #include <string> +#include "base/base_api.h" #include "base/basictypes.h" // Chromium and Chromium OS check out gtest to different places, so we're @@ -46,7 +47,7 @@ class Value; namespace base { -class JSONReader { +class BASE_API JSONReader { public: // A struct to hold a JS token. class Token { diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc index db0ab63..a7aeaf0 100644 --- a/base/json/json_reader_unittest.cc +++ b/base/json/json_reader_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" #include "base/json/json_reader.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/string_piece.h" #include "base/utf_string_conversions.h" #include "base/values.h" diff --git a/base/json/json_writer.h b/base/json/json_writer.h index eb17145..c019e87 100644 --- a/base/json/json_writer.h +++ b/base/json/json_writer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,13 +8,14 @@ #include <string> +#include "base/base_api.h" #include "base/basictypes.h" class Value; namespace base { -class JSONWriter { +class BASE_API JSONWriter { public: // Given a root node, generates a JSON string and puts it into |json|. // If |pretty_print| is true, return a slightly nicer formated json string diff --git a/base/json/string_escape.h b/base/json/string_escape.h index 2d7206b..e12e0bb 100644 --- a/base/json/string_escape.h +++ b/base/json/string_escape.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,6 +10,7 @@ #include <string> +#include "base/base_api.h" #include "base/string16.h" namespace base { @@ -19,19 +20,19 @@ namespace base { // If |put_in_quotes| is true, the result will be surrounded in double quotes. // The outputted literal, when interpreted by the browser, should result in a // javascript string that is identical and the same length as the input |str|. -void JsonDoubleQuote(const std::string& str, - bool put_in_quotes, - std::string* dst); +BASE_API void JsonDoubleQuote(const std::string& str, + bool put_in_quotes, + std::string* dst); // Same as above, but always returns the result double quoted. -std::string GetDoubleQuotedJson(const std::string& str); +BASE_API std::string GetDoubleQuotedJson(const std::string& str); -void JsonDoubleQuote(const string16& str, - bool put_in_quotes, - std::string* dst); +BASE_API void JsonDoubleQuote(const string16& str, + bool put_in_quotes, + std::string* dst); // Same as above, but always returns the result double quoted. -std::string GetDoubleQuotedJson(const string16& str); +BASE_API std::string GetDoubleQuotedJson(const string16& str); } // namespace base diff --git a/base/lazy_instance.h b/base/lazy_instance.h index a22dbf3..7b1bdc4 100644 --- a/base/lazy_instance.h +++ b/base/lazy_instance.h @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -39,6 +39,7 @@ #include <new> // For placement new. #include "base/atomicops.h" +#include "base/base_api.h" #include "base/basictypes.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_restrictions.h" @@ -80,7 +81,7 @@ void (*LeakyLazyInstanceTraits<Type>::Delete)(void* instance) = NULL; // We pull out some of the functionality into a non-templated base, so that we // can implement the more complicated pieces out of line in the .cc file. -class LazyInstanceHelper { +class BASE_API LazyInstanceHelper { protected: enum { STATE_EMPTY = 0, diff --git a/base/linux_util.cc b/base/linux_util.cc index 4e7cc5c..2f9f862 100644 --- a/base/linux_util.cc +++ b/base/linux_util.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -17,10 +17,10 @@ #include "base/command_line.h" #include "base/file_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" #include "base/path_service.h" #include "base/process_util.h" -#include "base/singleton.h" -#include "base/scoped_ptr.h" #include "base/string_util.h" #include "base/synchronization/lock.h" @@ -62,7 +62,7 @@ class LinuxDistroHelper { // Indicate the check finished, move to STATE_CHECK_FINISHED. void CheckFinished() { base::AutoLock scoped_lock(lock_); - DCHECK(state_ == STATE_CHECK_STARTED); + DCHECK_EQ(STATE_CHECK_STARTED, state_); state_ = STATE_CHECK_FINISHED; } diff --git a/base/logging.cc b/base/logging.cc index 57a2a89..430ae82 100644 --- a/base/logging.cc +++ b/base/logging.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -39,10 +39,11 @@ typedef FILE* FileHandle; typedef pthread_mutex_t* MutexHandle; #endif +#include <algorithm> +#include <cstring> #include <ctime> #include <iomanip> -#include <cstring> -#include <algorithm> +#include <ostream> #include "base/base_switches.h" #include "base/command_line.h" @@ -821,3 +822,15 @@ void RawLog(int level, const char* message) { std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) { return out << WideToUTF8(std::wstring(wstr)); } + +namespace base { + +// This was defined at the beginnig of this file. +#undef write + +std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { + o.write(piece.data(), static_cast<std::streamsize>(piece.size())); + return o; +} + +} // namespace base diff --git a/base/logging.h b/base/logging.h index baf8eb6..0e78e1a 100644 --- a/base/logging.h +++ b/base/logging.h @@ -10,7 +10,9 @@ #include <cstring> #include <sstream> +#include "base/base_api.h" #include "base/basictypes.h" +#include "build/build_config.h" // // Optional message capabilities @@ -190,11 +192,11 @@ typedef char PathChar; // Implementation of the InitLogging() method declared below. We use a // more-specific name so we can #define it above without affecting other code // that has named stuff "InitLogging". -bool BaseInitLoggingImpl(const PathChar* log_file, - LoggingDestination logging_dest, - LogLockingState lock_log, - OldFileDeletionState delete_old, - DcheckState dcheck_state); +BASE_API bool BaseInitLoggingImpl(const PathChar* log_file, + LoggingDestination logging_dest, + LogLockingState lock_log, + OldFileDeletionState delete_old, + DcheckState dcheck_state); // Sets the log file name and other global logging state. Calling this function // is recommended, and is normally done at the beginning of application init. @@ -221,19 +223,19 @@ inline bool InitLogging(const PathChar* log_file, // up to level INFO) if this function is not called. // Note that log messages for VLOG(x) are logged at level -x, so setting // the min log level to negative values enables verbose logging. -void SetMinLogLevel(int level); +BASE_API void SetMinLogLevel(int level); // Gets the current log level. -int GetMinLogLevel(); +BASE_API int GetMinLogLevel(); // Gets the VLOG default verbosity level. -int GetVlogVerbosity(); +BASE_API int GetVlogVerbosity(); // Gets the current vlog level for the given file (usually taken from // __FILE__). // Note that |N| is the size *with* the null terminator. -int GetVlogLevelHelper(const char* file_start, size_t N); +BASE_API int GetVlogLevelHelper(const char* file_start, size_t N); template <size_t N> int GetVlogLevel(const char (&file)[N]) { @@ -244,27 +246,27 @@ int GetVlogLevel(const char (&file)[N]) { // process and thread IDs default to off, the timestamp defaults to on. // If this function is not called, logging defaults to writing the timestamp // only. -void SetLogItems(bool enable_process_id, bool enable_thread_id, - bool enable_timestamp, bool enable_tickcount); +BASE_API void SetLogItems(bool enable_process_id, bool enable_thread_id, + bool enable_timestamp, bool enable_tickcount); // Sets whether or not you'd like to see fatal debug messages popped up in // a dialog box or not. // Dialogs are not shown by default. -void SetShowErrorDialogs(bool enable_dialogs); +BASE_API void SetShowErrorDialogs(bool enable_dialogs); // Sets the Log Assert Handler that will be used to notify of check failures. // The default handler shows a dialog box and then terminate the process, // however clients can use this function to override with their own handling // (e.g. a silent one for Unit Tests) typedef void (*LogAssertHandlerFunction)(const std::string& str); -void SetLogAssertHandler(LogAssertHandlerFunction handler); +BASE_API void SetLogAssertHandler(LogAssertHandlerFunction handler); // Sets the Log Report Handler that will be used to notify of check failures // in non-debug mode. The default handler shows a dialog box and continues // the execution, however clients can use this function to override with their // own handling. typedef void (*LogReportHandlerFunction)(const std::string& str); -void SetLogReportHandler(LogReportHandlerFunction handler); +BASE_API void SetLogReportHandler(LogReportHandlerFunction handler); // Sets the Log Message Handler that gets passed every log message before // it's sent to other log destinations (if any). @@ -272,8 +274,8 @@ void SetLogReportHandler(LogReportHandlerFunction handler); // should not be sent to other log destinations. typedef bool (*LogMessageHandlerFunction)(int severity, const char* file, int line, size_t message_start, const std::string& str); -void SetLogMessageHandler(LogMessageHandlerFunction handler); -LogMessageHandlerFunction GetLogMessageHandler(); +BASE_API void SetLogMessageHandler(LogMessageHandlerFunction handler); +BASE_API LogMessageHandlerFunction GetLogMessageHandler(); typedef int LogSeverity; const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity @@ -714,7 +716,7 @@ const LogSeverity LOG_DCHECK = LOG_INFO; // You shouldn't actually use LogMessage's constructor to log things, // though. You should use the LOG() macro (and variants thereof) // above. -class LogMessage { +class BASE_API LogMessage { public: LogMessage(const char* file, int line, LogSeverity severity, int ctr); @@ -792,7 +794,7 @@ inline void LogAtLevel(int const log_level, std::string const &msg) { // This class is used to explicitly ignore values in the conditional // logging macros. This avoids compiler warnings like "value computed // is not used" and "statement has no effect". -class LogMessageVoidify { +class BASE_API LogMessageVoidify { public: LogMessageVoidify() { } // This has to be an operator with a precedence lower than << but @@ -808,11 +810,11 @@ typedef int SystemErrorCode; // Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to // pull in windows.h just for GetLastError() and DWORD. -SystemErrorCode GetLastSystemErrorCode(); +BASE_API SystemErrorCode GetLastSystemErrorCode(); #if defined(OS_WIN) // Appends a formatted system message of the GetLastError() type. -class Win32ErrorLogMessage { +class BASE_API Win32ErrorLogMessage { public: Win32ErrorLogMessage(const char* file, int line, @@ -864,10 +866,10 @@ class ErrnoLogMessage { // NOTE: Since the log file is opened as necessary by the action of logging // statements, there's no guarantee that it will stay closed // after this call. -void CloseLogFile(); +BASE_API void CloseLogFile(); // Async signal safe logging mechanism. -void RawLog(int level, const char* message); +BASE_API void RawLog(int level, const char* message); #define RAW_LOG(level, message) logging::RawLog(logging::LOG_ ## level, message) @@ -885,7 +887,7 @@ void RawLog(int level, const char* message); // which is normally ASCII. It is relatively slow, so try not to use it for // common cases. Non-ASCII characters will be converted to UTF-8 by these // operators. -std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); +BASE_API std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) { return out << wstr.c_str(); } @@ -936,8 +938,8 @@ namespace base { class StringPiece; -// allow StringPiece to be logged (needed for unit testing). -extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece); +// Allows StringPiece to be logged. +BASE_API std::ostream& operator<<(std::ostream& o, const StringPiece& piece); } // namespace base diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc index bb6e3d1..5a2cb53 100644 --- a/base/logging_unittest.cc +++ b/base/logging_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -62,7 +62,10 @@ TEST_F(LoggingTest, BasicLogging) { SetMinLogLevel(LOG_INFO); EXPECT_TRUE(LOG_IS_ON(INFO)); - EXPECT_EQ(DEBUG_MODE != 0, DLOG_IS_ON(INFO)); + // As of g++-4.5, the first argument to EXPECT_EQ cannot be a + // constant expression. + const bool kIsDebugMode = (DEBUG_MODE != 0); + EXPECT_EQ(kIsDebugMode, DLOG_IS_ON(INFO)); EXPECT_TRUE(VLOG_IS_ON(0)); LOG(INFO) << mock_log_source.Log(); diff --git a/base/logging_win.cc b/base/logging_win.cc index f780b5e..a714665 100644 --- a/base/logging_win.cc +++ b/base/logging_win.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/logging_win.h" -#include "base/singleton.h" +#include "base/memory/singleton.h" #include <initguid.h> // NOLINT namespace logging { diff --git a/base/logging_win.h b/base/logging_win.h index 9058c84..bd69df9 100644 --- a/base/logging_win.h +++ b/base/logging_win.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,6 +7,8 @@ #pragma once #include <string> + +#include "base/base_api.h" #include "base/basictypes.h" #include "base/win/event_trace_provider.h" #include "base/logging.h" @@ -48,7 +50,7 @@ enum LogMessageTypes { // Trace provider class to drive log control and transport // with Event Tracing for Windows. -class LogEventProvider : public base::win::EtwTraceProvider { +class BASE_API LogEventProvider : public base::win::EtwTraceProvider { public: static LogEventProvider* GetInstance(); diff --git a/base/mac/OWNERS b/base/mac/OWNERS new file mode 100644 index 0000000..a3fc32f --- /dev/null +++ b/base/mac/OWNERS @@ -0,0 +1,2 @@ +mark@chromium.org +thakis@chromium.org diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm index 151d82f..3f41466 100644 --- a/base/mac/foundation_util.mm +++ b/base/mac/foundation_util.mm @@ -168,7 +168,7 @@ FilePath GetAppBundlePath(const FilePath& exec_name) { // Don't prepend '/' to the first component. std::vector<std::string>::const_iterator it = components.begin(); std::string bundle_name = *it; - DCHECK(it->length() > 0); + DCHECK_GT(it->length(), 0U); // If the first component ends in ".app", we're already done. if (it->length() > kExtLength && !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength)) @@ -181,7 +181,7 @@ FilePath GetAppBundlePath(const FilePath& exec_name) { // Go through the remaining components. for (++it; it != components.end(); ++it) { - DCHECK(it->length() > 0); + DCHECK_GT(it->length(), 0U); bundle_name += *it; diff --git a/base/mac/mac_util.mm b/base/mac/mac_util.mm index 2eddeae..2f93b23 100644 --- a/base/mac/mac_util.mm +++ b/base/mac/mac_util.mm @@ -9,7 +9,7 @@ #include "base/file_path.h" #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" -#include "base/scoped_nsobject.h" +#include "base/memory/scoped_nsobject.h" #include "base/sys_string_conversions.h" namespace base { @@ -17,7 +17,7 @@ namespace mac { namespace { -// a count of currently outstanding requests for full screen mode from browser +// The current count of outstanding requests for full screen mode from browser // windows, plugins, etc. int g_full_screen_requests[kNumFullScreenModes] = { 0, 0, 0}; @@ -75,7 +75,7 @@ bool WasLaunchedAsLoginItem() { } // Looks into Shared File Lists corresponding to Login Items for the item -// representing the current application. If such an item is found, returns +// representing the current application. If such an item is found, returns a // retained reference to it. Caller is responsible for releasing the reference. LSSharedFileListItemRef GetLoginItemForApp() { ScopedCFTypeRef<LSSharedFileListRef> login_items(LSSharedFileListCreate( @@ -276,7 +276,7 @@ bool SetFileBackupExclusion(const FilePath& file_path, bool exclude) { bool success = CSBackupSetItemExcluded((CFURLRef)url, exclude, true) == noErr; if (!success) - LOG(WARNING) << "Failed to set backup excluson for file '" + LOG(WARNING) << "Failed to set backup exclusion for file '" << file_path.value().c_str() << "'. Continuing."; return success; } diff --git a/base/mac/mac_util_unittest.mm b/base/mac/mac_util_unittest.mm index bae0019..b4f9268 100644 --- a/base/mac/mac_util_unittest.mm +++ b/base/mac/mac_util_unittest.mm @@ -9,7 +9,7 @@ #include "base/file_path.h" #include "base/file_util.h" #include "base/mac/scoped_cftyperef.h" -#include "base/scoped_nsobject.h" +#include "base/memory/scoped_nsobject.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" diff --git a/base/mach_ipc_mac.h b/base/mach_ipc_mac.h index d506a00..4e80f62 100644 --- a/base/mach_ipc_mac.h +++ b/base/mach_ipc_mac.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -140,6 +140,7 @@ class MachMsgPortDescriptor : public mach_msg_port_descriptor_t { // class MachMessage { public: + static const size_t kEmptyMessageSize; virtual ~MachMessage(); @@ -209,7 +210,6 @@ class MachMessage { // of the Mach header. size_t MaxSize() const { return storage_length_bytes_; } - protected: mach_msg_header_t *Head() { return &(storage_->head); } private: @@ -220,15 +220,6 @@ class MachMessage { u_int8_t padding[1024]; }; - // kEmptyMessageSize needs to have the definition of MachMessageData before - // it. - public: - // The size of an empty message with no data. - static const size_t kEmptyMessageSize = sizeof(mach_msg_header_t) + - sizeof(mach_msg_body_t) + - sizeof(MessageDataPacket); - - private: MachMessageData *storage_; size_t storage_length_bytes_; bool own_storage_; // Is storage owned by this object? diff --git a/base/mach_ipc_mac.mm b/base/mach_ipc_mac.mm index a0bfdc8..b6dedd2 100644 --- a/base/mach_ipc_mac.mm +++ b/base/mach_ipc_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,10 @@ namespace base { +// static +const size_t MachMessage::kEmptyMessageSize = sizeof(mach_msg_header_t) + + sizeof(mach_msg_body_t) + sizeof(MessageDataPacket); + //============================================================================== MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() { Initialize(message_id); @@ -50,7 +54,7 @@ MachMessage::MachMessage(void *storage, size_t storage_length) storage_length_bytes_(storage_length), own_storage_(false) { DCHECK(storage); - DCHECK(storage_length >= kEmptyMessageSize); + DCHECK_GE(storage_length, kEmptyMessageSize); } //============================================================================== @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,8 @@ #include <string> +#include "base/base_api.h" + // MD5 stands for Message Digest algorithm 5. // MD5 is a robust hash function, designed for cyptography, but often used // for file checksums. The code is complex and slow, but has few @@ -42,25 +44,25 @@ typedef char MD5Context[88]; // Computes the MD5 sum of the given data buffer with the given length. // The given 'digest' structure will be filled with the result data. -void MD5Sum(const void* data, size_t length, MD5Digest* digest); +BASE_API void MD5Sum(const void* data, size_t length, MD5Digest* digest); // Initializes the given MD5 context structure for subsequent calls to // MD5Update(). -void MD5Init(MD5Context* context); +BASE_API void MD5Init(MD5Context* context); // For the given buffer of data, updates the given MD5 context with the sum of // the data. You can call this any number of times during the computation, // except that MD5Init() must have been called first. -void MD5Update(MD5Context* context, const void* buf, size_t len); +BASE_API void MD5Update(MD5Context* context, const void* buf, size_t len); // Finalizes the MD5 operation and fills the buffer with the digest. -void MD5Final(MD5Digest* digest, MD5Context* pCtx); +BASE_API void MD5Final(MD5Digest* digest, MD5Context* pCtx); // Converts a digest into human-readable hexadecimal. -std::string MD5DigestToBase16(const MD5Digest& digest); +BASE_API std::string MD5DigestToBase16(const MD5Digest& digest); // Returns the MD5 (in hexadecimal) of a string. -std::string MD5String(const std::string& str); +BASE_API std::string MD5String(const std::string& str); #endif // BASE_MD5_H_ diff --git a/base/linked_ptr.h b/base/memory/linked_ptr.h index 162798d..41931d8 100644 --- a/base/linked_ptr.h +++ b/base/memory/linked_ptr.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -34,8 +34,8 @@ // - is thread safe for copying and deletion // - supports weak_ptrs -#ifndef BASE_LINKED_PTR_H_ -#define BASE_LINKED_PTR_H_ +#ifndef BASE_MEMORY_LINKED_PTR_H_ +#define BASE_MEMORY_LINKED_PTR_H_ #pragma once #include "base/logging.h" // for CHECK macros @@ -179,4 +179,4 @@ linked_ptr<T> make_linked_ptr(T* ptr) { return linked_ptr<T>(ptr); } -#endif // BASE_LINKED_PTR_H_ +#endif // BASE_MEMORY_LINKED_PTR_H_ diff --git a/base/linked_ptr_unittest.cc b/base/memory/linked_ptr_unittest.cc index e65b687..ae10fc2 100644 --- a/base/linked_ptr_unittest.cc +++ b/base/memory/linked_ptr_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <string> -#include "base/linked_ptr.h" +#include "base/memory/linked_ptr.h" #include "base/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/memory_debug.cc b/base/memory/memory_debug.cc index 7d048e6..f020b94 100644 --- a/base/memory_debug.cc +++ b/base/memory/memory_debug.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/memory_debug.h" +#include "base/memory/memory_debug.h" #ifdef PURIFY // this #define is used to prevent people from directly using pure.h diff --git a/base/memory_debug.h b/base/memory/memory_debug.h index 6d8c7f9..d094edb 100644 --- a/base/memory_debug.h +++ b/base/memory/memory_debug.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,15 +6,16 @@ // All methods are effectively no-ops unless this program is being run through // a supported memory tool (currently, only Purify) -#ifndef BASE_MEMORY_DEBUG_H_ -#define BASE_MEMORY_DEBUG_H_ +#ifndef BASE_MEMORY_MEMORY_DEBUG_H_ +#define BASE_MEMORY_MEMORY_DEBUG_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" namespace base { -class MemoryDebug { +class BASE_API MemoryDebug { public: // Since MIU messages are a lot of data, and we don't always want this data, // we have a global switch. If disabled, *MemoryInUse are no-ops. @@ -44,4 +45,4 @@ class MemoryDebug { } // namespace base -#endif // BASE_MEMORY_DEBUG_H_ +#endif // BASE_MEMORY_MEMORY_DEBUG_H_ diff --git a/base/raw_scoped_refptr_mismatch_checker.h b/base/memory/raw_scoped_refptr_mismatch_checker.h index b79cfb5..a4a50c3 100644 --- a/base/raw_scoped_refptr_mismatch_checker.h +++ b/base/memory/raw_scoped_refptr_mismatch_checker.h @@ -1,12 +1,12 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ -#define BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#ifndef BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#define BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ #pragma once -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/template_util.h" #include "base/tuple.h" #include "build/build_config.h" @@ -127,4 +127,4 @@ struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > { } // namespace base -#endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#endif // BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ diff --git a/base/ref_counted.cc b/base/memory/ref_counted.cc index 2d459ae..31ad509 100644 --- a/base/ref_counted.cc +++ b/base/memory/ref_counted.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/logging.h" #include "base/threading/thread_collision_warner.h" diff --git a/base/ref_counted.h b/base/memory/ref_counted.h index 4c3aeb8..1207ed4 100644 --- a/base/ref_counted.h +++ b/base/memory/ref_counted.h @@ -1,19 +1,20 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_REF_COUNTED_H_ -#define BASE_REF_COUNTED_H_ +#ifndef BASE_MEMORY_REF_COUNTED_H_ +#define BASE_MEMORY_REF_COUNTED_H_ #pragma once #include "base/atomic_ref_count.h" +#include "base/base_api.h" #include "base/threading/thread_collision_warner.h" namespace base { namespace subtle { -class RefCountedBase { +class BASE_API RefCountedBase { public: static bool ImplementsThreadSafeReferenceCounting() { return false; } @@ -39,7 +40,7 @@ class RefCountedBase { DISALLOW_COPY_AND_ASSIGN(RefCountedBase); }; -class RefCountedThreadSafeBase { +class BASE_API RefCountedThreadSafeBase { public: static bool ImplementsThreadSafeReferenceCounting() { return true; } @@ -295,4 +296,4 @@ scoped_refptr<T> make_scoped_refptr(T* t) { return scoped_refptr<T>(t); } -#endif // BASE_REF_COUNTED_H_ +#endif // BASE_MEMORY_REF_COUNTED_H_ diff --git a/base/ref_counted_memory.cc b/base/memory/ref_counted_memory.cc index dc244b9..aa16031 100644 --- a/base/ref_counted_memory.cc +++ b/base/memory/ref_counted_memory.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/ref_counted_memory.h" +#include "base/memory/ref_counted_memory.h" RefCountedMemory::RefCountedMemory() { } diff --git a/base/ref_counted_memory.h b/base/memory/ref_counted_memory.h index fe7427e..1a0f51e 100644 --- a/base/ref_counted_memory.h +++ b/base/memory/ref_counted_memory.h @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_REF_COUNTED_MEMORY_H_ -#define BASE_REF_COUNTED_MEMORY_H_ +#ifndef BASE_MEMORY_REF_COUNTED_MEMORY_H_ +#define BASE_MEMORY_REF_COUNTED_MEMORY_H_ #pragma once #include <vector> -#include "base/ref_counted.h" +#include "base/base_api.h" +#include "base/memory/ref_counted.h" // TODO(erg): The contents of this file should be in a namespace. This would // require touching >100 files in chrome/ though. @@ -16,7 +17,8 @@ // A generic interface to memory. This object is reference counted because one // of its two subclasses own the data they carry, and we need to have // heterogeneous containers of these two types of memory. -class RefCountedMemory : public base::RefCountedThreadSafe<RefCountedMemory> { +class BASE_API RefCountedMemory + : public base::RefCountedThreadSafe<RefCountedMemory> { public: // Retrieves a pointer to the beginning of the data we point to. If the data // is empty, this will return NULL. @@ -33,7 +35,7 @@ class RefCountedMemory : public base::RefCountedThreadSafe<RefCountedMemory> { // An implementation of RefCountedMemory, where the ref counting does not // matter. -class RefCountedStaticMemory : public RefCountedMemory { +class BASE_API RefCountedStaticMemory : public RefCountedMemory { public: RefCountedStaticMemory() : data_(NULL), length_(0) {} @@ -53,7 +55,7 @@ class RefCountedStaticMemory : public RefCountedMemory { // An implementation of RefCountedMemory, where we own our the data in a // vector. -class RefCountedBytes : public RefCountedMemory { +class BASE_API RefCountedBytes : public RefCountedMemory { public: RefCountedBytes(); @@ -79,4 +81,4 @@ class RefCountedBytes : public RefCountedMemory { DISALLOW_COPY_AND_ASSIGN(RefCountedBytes); }; -#endif // BASE_REF_COUNTED_MEMORY_H_ +#endif // BASE_MEMORY_REF_COUNTED_MEMORY_H_ diff --git a/base/ref_counted_unittest.cc b/base/memory/ref_counted_unittest.cc index cd6f922..dcc292f 100644 --- a/base/ref_counted_unittest.cc +++ b/base/memory/ref_counted_unittest.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/ref_counted.h" #include "testing/gtest/include/gtest/gtest.h" -#include "base/ref_counted.h" namespace { diff --git a/base/scoped_callback_factory.h b/base/memory/scoped_callback_factory.h index a2fc1f0..a9c58a0 100644 --- a/base/scoped_callback_factory.h +++ b/base/memory/scoped_callback_factory.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -33,11 +33,11 @@ // callback runs, it will notice that the MyClass instance is dead, and it will // avoid calling the GotData method. -#ifndef BASE_SCOPED_CALLBACK_FACTORY_H_ -#define BASE_SCOPED_CALLBACK_FACTORY_H_ +#ifndef BASE_MEMORY_SCOPED_CALLBACK_FACTORY_H_ +#define BASE_MEMORY_SCOPED_CALLBACK_FACTORY_H_ #include "base/callback.h" -#include "base/weak_ptr.h" +#include "base/memory/weak_ptr.h" namespace base { @@ -130,4 +130,4 @@ class ScopedCallbackFactory { } // namespace base -#endif // BASE_SCOPED_CALLBACK_FACTORY_H_ +#endif // BASE_MEMORY_SCOPED_CALLBACK_FACTORY_H_ diff --git a/base/scoped_handle.h b/base/memory/scoped_handle.h index 90cb5d5..232d83e 100644 --- a/base/scoped_handle.h +++ b/base/memory/scoped_handle.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SCOPED_HANDLE_H_ -#define BASE_SCOPED_HANDLE_H_ +#ifndef BASE_MEMORY_SCOPED_HANDLE_H_ +#define BASE_MEMORY_SCOPED_HANDLE_H_ #pragma once #include <stdio.h> @@ -48,4 +48,4 @@ class ScopedStdioHandle { DISALLOW_COPY_AND_ASSIGN(ScopedStdioHandle); }; -#endif // BASE_SCOPED_HANDLE_H_ +#endif // BASE_MEMORY_SCOPED_HANDLE_H_ diff --git a/base/scoped_native_library.cc b/base/memory/scoped_native_library.cc index 9d34449..c1e6afc 100644 --- a/base/scoped_native_library.cc +++ b/base/memory/scoped_native_library.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/scoped_native_library.h" +#include "base/memory/scoped_native_library.h" namespace base { @@ -14,7 +14,7 @@ ScopedNativeLibrary::ScopedNativeLibrary(NativeLibrary library) } ScopedNativeLibrary::ScopedNativeLibrary(const FilePath& library_path) { - library_ = base::LoadNativeLibrary(library_path); + library_ = base::LoadNativeLibrary(library_path, NULL); } ScopedNativeLibrary::~ScopedNativeLibrary() { diff --git a/base/scoped_native_library.h b/base/memory/scoped_native_library.h index 28b29b3..56116b9 100644 --- a/base/scoped_native_library.h +++ b/base/memory/scoped_native_library.h @@ -1,11 +1,12 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SCOPED_NATIVE_LIBRARY_H_ -#define BASE_SCOPED_NATIVE_LIBRARY_H_ +#ifndef BASE_MEMORY_SCOPED_NATIVE_LIBRARY_H_ +#define BASE_MEMORY_SCOPED_NATIVE_LIBRARY_H_ #pragma once +#include "base/base_api.h" #include "base/native_library.h" class FilePath; @@ -15,7 +16,7 @@ namespace base { // A class which encapsulates a base::NativeLibrary object available only in a // scope. // This class automatically unloads the loaded library in its destructor. -class ScopedNativeLibrary { +class BASE_API ScopedNativeLibrary { public: // Initializes with a NULL library. ScopedNativeLibrary(); @@ -49,4 +50,4 @@ class ScopedNativeLibrary { } // namespace base -#endif // BASE_SCOPED_NATIVE_LIBRARY_H_ +#endif // BASE_MEMORY_SCOPED_NATIVE_LIBRARY_H_ diff --git a/base/scoped_native_library_unittest.cc b/base/memory/scoped_native_library_unittest.cc index 567239d..0cc60e2 100644 --- a/base/scoped_native_library_unittest.cc +++ b/base/memory/scoped_native_library_unittest.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/scoped_native_library.h" +#include "base/memory/scoped_native_library.h" #if defined(OS_WIN) #include "base/file_path.h" #endif diff --git a/base/scoped_nsobject.h b/base/memory/scoped_nsobject.h index a9783e0..235ac39 100644 --- a/base/scoped_nsobject.h +++ b/base/memory/scoped_nsobject.h @@ -1,9 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SCOPED_NSOBJECT_H_ -#define BASE_SCOPED_NSOBJECT_H_ +#ifndef BASE_MEMORY_SCOPED_NSOBJECT_H_ +#define BASE_MEMORY_SCOPED_NSOBJECT_H_ #pragma once #import <Foundation/Foundation.h> @@ -164,4 +164,4 @@ class scoped_nsobject<NSAutoreleasePool> { DISALLOW_COPY_AND_ASSIGN(scoped_nsobject); }; -#endif // BASE_SCOPED_NSOBJECT_H_ +#endif // BASE_MEMORY_SCOPED_NSOBJECT_H_ diff --git a/base/scoped_open_process.h b/base/memory/scoped_open_process.h index 641f8e5..d5bdd95 100644 --- a/base/scoped_open_process.h +++ b/base/memory/scoped_open_process.h @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SCOPED_OPEN_PROCESS_H_ -#define BASE_SCOPED_OPEN_PROCESS_H_ +#ifndef BASE_MEMORY_SCOPED_OPEN_PROCESS_H_ +#define BASE_MEMORY_SCOPED_OPEN_PROCESS_H_ #pragma once #include "base/process.h" @@ -47,4 +47,4 @@ class ScopedOpenProcess { }; } // namespace base -#endif // BASE_SCOPED_OPEN_PROCESS_H_ +#endif // BASE_MEMORY_SCOPED_OPEN_PROCESS_H_ diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h new file mode 100644 index 0000000..1067d42 --- /dev/null +++ b/base/memory/scoped_ptr.h @@ -0,0 +1,383 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Scopers help you manage ownership of a pointer, helping you easily manage the +// a pointer within a scope, and automatically destroying the pointer at the +// end of a scope. There are two main classes you will use, which correspond +// to the operators new/delete and new[]/delete[]. +// +// Example usage (scoped_ptr): +// { +// scoped_ptr<Foo> foo(new Foo("wee")); +// } // foo goes out of scope, releasing the pointer with it. +// +// { +// scoped_ptr<Foo> foo; // No pointer managed. +// foo.reset(new Foo("wee")); // Now a pointer is managed. +// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. +// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. +// foo->Method(); // Foo::Method() called. +// foo.get()->Method(); // Foo::Method() called. +// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer +// // manages a pointer. +// foo.reset(new Foo("wee4")); // foo manages a pointer again. +// foo.reset(); // Foo("wee4") destroyed, foo no longer +// // manages a pointer. +// } // foo wasn't managing a pointer, so nothing was destroyed. +// +// Example usage (scoped_array): +// { +// scoped_array<Foo> foo(new Foo[100]); +// foo.get()->Method(); // Foo::Method on the 0th element. +// foo[10].Method(); // Foo::Method on the 10th element. +// } + +#ifndef BASE_MEMORY_SCOPED_PTR_H_ +#define BASE_MEMORY_SCOPED_PTR_H_ +#pragma once + +// This is an implementation designed to match the anticipated future TR2 +// implementation of the scoped_ptr class, and its closely-related brethren, +// scoped_array, scoped_ptr_malloc. + +#include <assert.h> +#include <stddef.h> +#include <stdlib.h> + +#include "base/compiler_specific.h" + +// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> +// automatically deletes the pointer it holds (if any). +// That is, scoped_ptr<T> owns the T object that it points to. +// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. +// Also like T*, scoped_ptr<T> is thread-compatible, and once you +// dereference it, you get the threadsafety guarantees of T. +// +// The size of a scoped_ptr is small: +// sizeof(scoped_ptr<C>) == sizeof(C*) +template <class C> +class scoped_ptr { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to initializing with NULL. + // There is no way to create an uninitialized scoped_ptr. + // The input parameter must be allocated with new. + explicit scoped_ptr(C* p = NULL) : ptr_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + ptr_ = p; + } + } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + C& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } + C* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + C* get() const { return ptr_; } + + // Comparison operators. + // These return whether two scoped_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(C* p) const { return ptr_ == p; } + bool operator!=(C* p) const { return ptr_ != p; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + C* tmp = ptr_; + ptr_ = p2.ptr_; + p2.ptr_ = tmp; + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() WARN_UNUSED_RESULT { + C* retVal = ptr_; + ptr_ = NULL; + return retVal; + } + + private: + C* ptr_; + + // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't + // make sense, and if C2 == C, it still doesn't make sense because you should + // never have the same object owned by two different scoped_ptrs. + template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; + template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; + + // Disallow evil constructors + scoped_ptr(const scoped_ptr&); + void operator=(const scoped_ptr&); +}; + +// Free functions +template <class C> +void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { + p1.swap(p2); +} + +template <class C> +bool operator==(C* p1, const scoped_ptr<C>& p2) { + return p1 == p2.get(); +} + +template <class C> +bool operator!=(C* p1, const scoped_ptr<C>& p2) { + return p1 != p2.get(); +} + +// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate +// with new [] and the destructor deletes objects with delete []. +// +// As with scoped_ptr<C>, a scoped_array<C> either points to an object +// or is NULL. A scoped_array<C> owns the object that it points to. +// scoped_array<T> is thread-compatible, and once you index into it, +// the returned objects have only the threadsafety guarantees of T. +// +// Size: sizeof(scoped_array<C>) == sizeof(C*) +template <class C> +class scoped_array { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized scoped_array. + // The input parameter must be allocated with new []. + explicit scoped_array(C* p = NULL) : array_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_array() { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != array_) { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + array_ = p; + } + } + + // Get one element of the current object. + // Will assert() if there is no current object, or index i is negative. + C& operator[](ptrdiff_t i) const { + assert(i >= 0); + assert(array_ != NULL); + return array_[i]; + } + + // Get a pointer to the zeroth element of the current object. + // If there is no current object, return NULL. + C* get() const { + return array_; + } + + // Comparison operators. + // These return whether two scoped_array refer to the same object, not just to + // two different but equal objects. + bool operator==(C* p) const { return array_ == p; } + bool operator!=(C* p) const { return array_ != p; } + + // Swap two scoped arrays. + void swap(scoped_array& p2) { + C* tmp = array_; + array_ = p2.array_; + p2.array_ = tmp; + } + + // Release an array. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() WARN_UNUSED_RESULT { + C* retVal = array_; + array_ = NULL; + return retVal; + } + + private: + C* array_; + + // Forbid comparison of different scoped_array types. + template <class C2> bool operator==(scoped_array<C2> const& p2) const; + template <class C2> bool operator!=(scoped_array<C2> const& p2) const; + + // Disallow evil constructors + scoped_array(const scoped_array&); + void operator=(const scoped_array&); +}; + +// Free functions +template <class C> +void swap(scoped_array<C>& p1, scoped_array<C>& p2) { + p1.swap(p2); +} + +template <class C> +bool operator==(C* p1, const scoped_array<C>& p2) { + return p1 == p2.get(); +} + +template <class C> +bool operator!=(C* p1, const scoped_array<C>& p2) { + return p1 != p2.get(); +} + +// This class wraps the c library function free() in a class that can be +// passed as a template argument to scoped_ptr_malloc below. +class ScopedPtrMallocFree { + public: + inline void operator()(void* x) const { + free(x); + } +}; + +// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a +// second template argument, the functor used to free the object. + +template<class C, class FreeProc = ScopedPtrMallocFree> +class scoped_ptr_malloc { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to initializing with NULL. + // There is no way to create an uninitialized scoped_ptr. + // The input parameter must be allocated with an allocator that matches the + // Free functor. For the default Free functor, this is malloc, calloc, or + // realloc. + explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} + + // Destructor. If there is a C object, call the Free functor. + ~scoped_ptr_malloc() { + free_(ptr_); + } + + // Reset. Calls the Free functor on the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (ptr_ != p) { + free_(ptr_); + ptr_ = p; + } + } + + // Get the current object. + // operator* and operator-> will cause an assert() failure if there is + // no current object. + C& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } + + C* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + + C* get() const { + return ptr_; + } + + // Comparison operators. + // These return whether a scoped_ptr_malloc and a plain pointer refer + // to the same object, not just to two different but equal objects. + // For compatibility with the boost-derived implementation, these + // take non-const arguments. + bool operator==(C* p) const { + return ptr_ == p; + } + + bool operator!=(C* p) const { + return ptr_ != p; + } + + // Swap two scoped pointers. + void swap(scoped_ptr_malloc & b) { + C* tmp = b.ptr_; + b.ptr_ = ptr_; + ptr_ = tmp; + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() WARN_UNUSED_RESULT { + C* tmp = ptr_; + ptr_ = NULL; + return tmp; + } + + private: + C* ptr_; + + // no reason to use these: each scoped_ptr_malloc should have its own object + template <class C2, class GP> + bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; + template <class C2, class GP> + bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; + + static FreeProc const free_; + + // Disallow evil constructors + scoped_ptr_malloc(const scoped_ptr_malloc&); + void operator=(const scoped_ptr_malloc&); +}; + +template<class C, class FP> +FP const scoped_ptr_malloc<C, FP>::free_ = FP(); + +template<class C, class FP> inline +void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { + a.swap(b); +} + +template<class C, class FP> inline +bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { + return p == b.get(); +} + +template<class C, class FP> inline +bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { + return p != b.get(); +} + +#endif // BASE_MEMORY_SCOPED_PTR_H_ diff --git a/base/scoped_ptr_unittest.cc b/base/memory/scoped_ptr_unittest.cc index 99b1bc0..7519051 100644 --- a/base/scoped_ptr_unittest.cc +++ b/base/memory/scoped_ptr_unittest.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/basictypes.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/base/scoped_temp_dir.cc b/base/memory/scoped_temp_dir.cc index 000ed0a..f7db15d 100644 --- a/base/scoped_temp_dir.cc +++ b/base/memory/scoped_temp_dir.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/scoped_temp_dir.h" +#include "base/memory/scoped_temp_dir.h" #include "base/file_util.h" #include "base/logging.h" diff --git a/base/scoped_temp_dir.h b/base/memory/scoped_temp_dir.h index 4286d28..4c0a73f 100644 --- a/base/scoped_temp_dir.h +++ b/base/memory/scoped_temp_dir.h @@ -1,9 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SCOPED_TEMP_DIR_H_ -#define BASE_SCOPED_TEMP_DIR_H_ +#ifndef BASE_MEMORY_SCOPED_TEMP_DIR_H_ +#define BASE_MEMORY_SCOPED_TEMP_DIR_H_ #pragma once // An object representing a temporary / scratch directory that should be cleaned @@ -16,9 +16,10 @@ // (CreateUniqueTempDir, CreateUniqueTempDirUnderPath, and Set) must have // intervening calls to Delete or Take, or the calls will fail. +#include "base/base_api.h" #include "base/file_path.h" -class ScopedTempDir { +class BASE_API ScopedTempDir { public: // No directory is owned/created initially. ScopedTempDir(); @@ -55,4 +56,4 @@ class ScopedTempDir { DISALLOW_COPY_AND_ASSIGN(ScopedTempDir); }; -#endif // BASE_SCOPED_TEMP_DIR_H_ +#endif // BASE_MEMORY_SCOPED_TEMP_DIR_H_ diff --git a/base/scoped_temp_dir_unittest.cc b/base/memory/scoped_temp_dir_unittest.cc index 135c2fd..a83856f 100644 --- a/base/scoped_temp_dir_unittest.cc +++ b/base/memory/scoped_temp_dir_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/file_util.h" +#include "base/memory/scoped_temp_dir.h" #include "base/platform_file.h" -#include "base/scoped_temp_dir.h" #include "testing/gtest/include/gtest/gtest.h" TEST(ScopedTempDir, FullPath) { diff --git a/base/scoped_vector.h b/base/memory/scoped_vector.h index 9d372f3..6e0cf05 100644 --- a/base/scoped_vector.h +++ b/base/memory/scoped_vector.h @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SCOPED_VECTOR_H_ -#define BASE_SCOPED_VECTOR_H_ +#ifndef BASE_MEMORY_SCOPED_VECTOR_H_ +#define BASE_MEMORY_SCOPED_VECTOR_H_ #pragma once #include <vector> @@ -62,6 +62,12 @@ class ScopedVector { return v.insert(position, x); } + // Lets the ScopedVector take ownership of elements in [first,last). + template<typename InputIterator> + void insert(iterator position, InputIterator first, InputIterator last) { + v.insert(position, first, last); + } + iterator erase(iterator position) { delete *position; return v.erase(position); @@ -87,4 +93,4 @@ class ScopedVector { DISALLOW_COPY_AND_ASSIGN(ScopedVector); }; -#endif // BASE_SCOPED_VECTOR_H_ +#endif // BASE_MEMORY_SCOPED_VECTOR_H_ diff --git a/base/memory/scoped_vector_unittest.cc b/base/memory/scoped_vector_unittest.cc new file mode 100644 index 0000000..d2f3d0a --- /dev/null +++ b/base/memory/scoped_vector_unittest.cc @@ -0,0 +1,156 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// The LifeCycleObject notifies its Observer upon construction & destruction. +class LifeCycleObject { + public: + class Observer { + public: + virtual void OnLifeCycleConstruct(LifeCycleObject* o) = 0; + virtual void OnLifeCycleDestroy(LifeCycleObject* o) = 0; + + protected: + virtual ~Observer() {} + }; + + explicit LifeCycleObject(Observer* observer) + : observer_(observer) { + observer_->OnLifeCycleConstruct(this); + } + + ~LifeCycleObject() { + observer_->OnLifeCycleDestroy(this); + } + + private: + Observer* observer_; + + DISALLOW_COPY_AND_ASSIGN(LifeCycleObject); +}; + +// The life cycle states we care about for the purposes of testing ScopedVector +// against objects. +enum LifeCycleState { + LC_INITIAL, + LC_CONSTRUCTED, + LC_DESTROYED, +}; + +// Because we wish to watch the life cycle of an object being constructed and +// destroyed, and further wish to test expectations against the state of that +// object, we cannot save state in that object itself. Instead, we use this +// pairing of the watcher, which observes the object and notifies of +// construction & destruction. Since we also may be testing assumptions about +// things not getting freed, this class also acts like a scoping object and +// deletes the |constructed_life_cycle_object_|, if any when the +// LifeCycleWatcher is destroyed. To keep this simple, the only expected state +// changes are: +// INITIAL -> CONSTRUCTED -> DESTROYED. +// Anything more complicated than that should start another test. +class LifeCycleWatcher : public LifeCycleObject::Observer { + public: + LifeCycleWatcher() + : life_cycle_state_(LC_INITIAL), + constructed_life_cycle_object_(NULL) {} + ~LifeCycleWatcher() { + } + + // Assert INITIAL -> CONSTRUCTED and no LifeCycleObject associated with this + // LifeCycleWatcher. + virtual void OnLifeCycleConstruct(LifeCycleObject* object) { + ASSERT_EQ(LC_INITIAL, life_cycle_state_); + ASSERT_EQ(NULL, constructed_life_cycle_object_.get()); + life_cycle_state_ = LC_CONSTRUCTED; + constructed_life_cycle_object_.reset(object); + } + + // Assert CONSTRUCTED -> DESTROYED and the |object| being destroyed is the + // same one we saw constructed. + virtual void OnLifeCycleDestroy(LifeCycleObject* object) { + ASSERT_EQ(LC_CONSTRUCTED, life_cycle_state_); + LifeCycleObject* constructed_life_cycle_object = + constructed_life_cycle_object_.release(); + ASSERT_EQ(constructed_life_cycle_object, object); + life_cycle_state_ = LC_DESTROYED; + } + + LifeCycleState life_cycle_state() const { return life_cycle_state_; } + + // Factory method for creating a new LifeCycleObject tied to this + // LifeCycleWatcher. + LifeCycleObject* NewLifeCycleObject() { + return new LifeCycleObject(this); + } + + private: + LifeCycleState life_cycle_state_; + scoped_ptr<LifeCycleObject> constructed_life_cycle_object_; + + DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher); +}; + +TEST(ScopedVectorTest, LifeCycleWatcher) { + LifeCycleWatcher watcher; + EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); + LifeCycleObject* object = watcher.NewLifeCycleObject(); + EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); + delete object; + EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); +} + +TEST(ScopedVectorTest, Reset) { + LifeCycleWatcher watcher; + EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); + ScopedVector<LifeCycleObject> scoped_vector; + scoped_vector.push_back(watcher.NewLifeCycleObject()); + EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); + scoped_vector.reset(); + EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); +} + +TEST(ScopedVectorTest, Scope) { + LifeCycleWatcher watcher; + EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state()); + { + ScopedVector<LifeCycleObject> scoped_vector; + scoped_vector.push_back(watcher.NewLifeCycleObject()); + EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state()); + } + EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state()); +} + +TEST(ScopedVectorTest, InsertRange) { + LifeCycleWatcher watchers[5]; + + std::vector<LifeCycleObject*> vec; + for(LifeCycleWatcher* it = watchers; it != watchers + arraysize(watchers); + ++it) { + EXPECT_EQ(LC_INITIAL, it->life_cycle_state()); + vec.push_back(it->NewLifeCycleObject()); + EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); + } + // Start scope for ScopedVector. + { + ScopedVector<LifeCycleObject> scoped_vector; + scoped_vector.insert(scoped_vector.end(), vec.begin() + 1, vec.begin() + 3); + for(LifeCycleWatcher* it = watchers; it != watchers + arraysize(watchers); + ++it) + EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); + } + for(LifeCycleWatcher* it = watchers; it != watchers + 1; ++it) + EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); + for(LifeCycleWatcher* it = watchers + 1; it != watchers + 3; ++it) + EXPECT_EQ(LC_DESTROYED, it->life_cycle_state()); + for(LifeCycleWatcher* it = watchers + 3; it != watchers + arraysize(watchers); + ++it) + EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state()); +} + +} // namespace diff --git a/base/singleton.h b/base/memory/singleton.h index 0fe5e27..a387356 100644 --- a/base/singleton.h +++ b/base/memory/singleton.h @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SINGLETON_H_ -#define BASE_SINGLETON_H_ +#ifndef BASE_MEMORY_SINGLETON_H_ +#define BASE_MEMORY_SINGLETON_H_ #pragma once #include "base/at_exit.h" @@ -126,7 +126,7 @@ template <typename Type> base::subtle::Atomic32 // Example usage: // // In your header: -// #include "base/singleton.h" +// #include "base/memory/singleton.h" // class FooClass { // public: // static FooClass* GetInstance(); <-- See comment below on this. @@ -268,4 +268,4 @@ template <typename Type, typename Traits, typename DifferentiatingType> base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>:: instance_ = 0; -#endif // BASE_SINGLETON_H_ +#endif // BASE_MEMORY_SINGLETON_H_ diff --git a/base/singleton_objc.h b/base/memory/singleton_objc.h index e28c8a5..8531556 100644 --- a/base/singleton_objc.h +++ b/base/memory/singleton_objc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -27,12 +27,12 @@ // ... // Foo* widgetSingleton = SingletonObjC<Foo, FooSingletonTraits>::get(); -#ifndef BASE_SINGLETON_OBJC_H_ -#define BASE_SINGLETON_OBJC_H_ +#ifndef BASE_MEMORY_SINGLETON_OBJC_H_ +#define BASE_MEMORY_SINGLETON_OBJC_H_ #pragma once #import <Foundation/Foundation.h> -#include "base/singleton.h" +#include "base/memory/singleton.h" // Singleton traits usable to manage traditional Objective-C objects, which // are instantiated by sending |alloc| and |init| messages, and are deallocated @@ -58,4 +58,4 @@ template<typename Type, class SingletonObjC : public Singleton<Type, Traits, DifferentiatingType> { }; -#endif // BASE_SINGLETON_OBJC_H_ +#endif // BASE_MEMORY_SINGLETON_OBJC_H_ diff --git a/base/singleton_unittest.cc b/base/memory/singleton_unittest.cc index 3d7e7e6..a605885 100644 --- a/base/singleton_unittest.cc +++ b/base/memory/singleton_unittest.cc @@ -1,11 +1,11 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/at_exit.h" #include "base/file_util.h" +#include "base/memory/singleton.h" #include "base/path_service.h" -#include "base/singleton.h" #include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/base/weak_ptr.cc b/base/memory/weak_ptr.cc index 86c89c1..30c777c 100644 --- a/base/weak_ptr.cc +++ b/base/memory/weak_ptr.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/weak_ptr.h" +#include "base/memory/weak_ptr.h" namespace base { namespace internal { @@ -10,19 +10,19 @@ namespace internal { WeakReference::Flag::Flag(Flag** handle) : handle_(handle) { } -WeakReference::Flag::~Flag() { - if (handle_) - *handle_ = NULL; +void WeakReference::Flag::Invalidate() { + DCHECK(thread_checker_.CalledOnValidThread()); + handle_ = NULL; } -void WeakReference::Flag::AddRef() const { - DCHECK(CalledOnValidThread()); - RefCounted<Flag>::AddRef(); +bool WeakReference::Flag::IsValid() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return handle_ != NULL; } -void WeakReference::Flag::Release() const { - DCHECK(CalledOnValidThread()); - RefCounted<Flag>::Release(); +WeakReference::Flag::~Flag() { + if (handle_) + *handle_ = NULL; } WeakReference::WeakReference() { @@ -35,7 +35,7 @@ WeakReference::~WeakReference() { } bool WeakReference::is_valid() const { - return flag_ && flag_->is_valid(); + return flag_ && flag_->IsValid(); } WeakReferenceOwner::WeakReferenceOwner() : flag_(NULL) { diff --git a/base/weak_ptr.h b/base/memory/weak_ptr.h index 6168367..0c6b4a7 100644 --- a/base/weak_ptr.h +++ b/base/memory/weak_ptr.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -48,13 +48,14 @@ // WARNING: weak pointers are not threadsafe!!! You must only use a WeakPtr // instance on thread where it was created. -#ifndef BASE_WEAK_PTR_H_ -#define BASE_WEAK_PTR_H_ +#ifndef BASE_MEMORY_WEAK_PTR_H_ +#define BASE_MEMORY_WEAK_PTR_H_ #pragma once +#include "base/base_api.h" #include "base/logging.h" -#include "base/ref_counted.h" -#include "base/threading/non_thread_safe.h" +#include "base/memory/ref_counted.h" +#include "base/threading/thread_checker.h" namespace base { @@ -62,21 +63,25 @@ namespace internal { // These classes are part of the WeakPtr implementation. // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. -class WeakReference { +class BASE_API WeakReference { public: - class Flag : public RefCounted<Flag>, public base::NonThreadSafe { + // While Flag is bound to a specific thread, it may be deleted from another + // via base::WeakPtr::~WeakPtr(). + class Flag : public RefCountedThreadSafe<Flag> { public: - Flag(Flag** handle); - ~Flag(); + explicit Flag(Flag** handle); - void AddRef() const; - void Release() const; - void Invalidate() { handle_ = NULL; } - bool is_valid() const { return handle_ != NULL; } + void Invalidate(); + bool IsValid() const; - void DetachFromThread() { base::NonThreadSafe::DetachFromThread(); } + void DetachFromThread() { thread_checker_.DetachFromThread(); } private: + friend class base::RefCountedThreadSafe<Flag>; + + ~Flag(); + + ThreadChecker thread_checker_; Flag** handle_; }; @@ -90,7 +95,7 @@ class WeakReference { scoped_refptr<Flag> flag_; }; -class WeakReferenceOwner { +class BASE_API WeakReferenceOwner { public: WeakReferenceOwner(); ~WeakReferenceOwner(); @@ -116,7 +121,7 @@ class WeakReferenceOwner { // constructor by avoiding the need for a public accessor for ref_. A // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this // base class gives us a way to access ref_ in a protected fashion. -class WeakPtrBase { +class BASE_API WeakPtrBase { public: WeakPtrBase(); ~WeakPtrBase(); @@ -234,6 +239,11 @@ class WeakPtrFactory { return weak_reference_owner_.HasRefs(); } + // Indicates that this object will be used on another thread from now on. + void DetachFromThread() { + weak_reference_owner_.DetachFromThread(); + } + private: internal::WeakReferenceOwner weak_reference_owner_; T* ptr_; @@ -242,4 +252,4 @@ class WeakPtrFactory { } // namespace base -#endif // BASE_WEAK_PTR_H_ +#endif // BASE_MEMORY_WEAK_PTR_H_ diff --git a/base/weak_ptr_unittest.cc b/base/memory/weak_ptr_unittest.cc index bcaca9e..6c2a7e8 100644 --- a/base/weak_ptr_unittest.cc +++ b/base/memory/weak_ptr_unittest.cc @@ -1,12 +1,12 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "base/message_loop.h" #include "base/threading/thread.h" -#include "base/scoped_ptr.h" -#include "base/weak_ptr.h" namespace base { namespace { diff --git a/base/message_loop.cc b/base/message_loop.cc index f726dfc..f23caa0 100644 --- a/base/message_loop.cc +++ b/base/message_loop.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -122,7 +122,11 @@ MessageLoop::MessageLoop(Type type) : type_(type), nestable_tasks_allowed_(true), exception_restoration_(false), + message_histogram_(NULL), state_(NULL), +#ifdef OS_WIN + os_modal_loop_(false), +#endif // OS_WIN next_sequence_num_(0) { DCHECK(!current()) << "should only have one message loop per thread"; lazy_tls_ptr.Pointer()->Set(this); @@ -533,7 +537,7 @@ void MessageLoop::PostTask_Helper( // on each thread. void MessageLoop::StartHistogrammer() { - if (enable_histogrammer_ && !message_histogram_.get() + if (enable_histogrammer_ && !message_histogram_ && base::StatisticsRecorder::IsActive()) { DCHECK(!thread_name_.empty()); message_histogram_ = base::LinearHistogram::FactoryGet( @@ -546,7 +550,7 @@ void MessageLoop::StartHistogrammer() { } void MessageLoop::HistogramEvent(int event) { - if (message_histogram_.get()) + if (message_histogram_) message_histogram_->Add(event); } diff --git a/base/message_loop.h b/base/message_loop.h index c1dce43..519e4a3 100644 --- a/base/message_loop.h +++ b/base/message_loop.h @@ -9,10 +9,11 @@ #include <queue> #include <string> +#include "base/base_api.h" #include "base/basictypes.h" +#include "base/memory/ref_counted.h" #include "base/message_pump.h" #include "base/observer_list.h" -#include "base/ref_counted.h" #include "base/synchronization/lock.h" #include "base/task.h" @@ -65,7 +66,7 @@ class Histogram; // Please be SURE your task is reentrant (nestable) and all global variables // are stable and accessible before calling SetNestableTasksAllowed(true). // -class MessageLoop : public base::MessagePump::Delegate { +class BASE_API MessageLoop : public base::MessagePump::Delegate { public: #if defined(OS_WIN) typedef base::MessagePumpWin::Dispatcher Dispatcher; @@ -117,7 +118,7 @@ class MessageLoop : public base::MessagePump::Delegate { // NOTE: Any tasks posted to the MessageLoop during this notification will // not be run. Instead, they will be deleted. // - class DestructionObserver { + class BASE_API DestructionObserver { public: virtual void WillDestroyCurrentMessageLoop() = 0; @@ -283,7 +284,7 @@ class MessageLoop : public base::MessagePump::Delegate { // MessageLoop. // // NOTE: A TaskObserver implementation should be extremely fast! - class TaskObserver { + class BASE_API TaskObserver { public: TaskObserver(); @@ -319,6 +320,16 @@ class MessageLoop : public base::MessagePump::Delegate { // Asserts that the MessageLoop is "idle". void AssertIdle() const; +#if defined(OS_WIN) + void set_os_modal_loop(bool os_modal_loop) { + os_modal_loop_ = os_modal_loop; + } + + bool os_modal_loop() const { + return os_modal_loop_; + } +#endif // OS_WIN + //---------------------------------------------------------------------------- protected: struct RunState { @@ -462,7 +473,7 @@ class MessageLoop : public base::MessagePump::Delegate { std::string thread_name_; // A profiling histogram showing the counts of various messages and events. - scoped_refptr<base::Histogram> message_histogram_; + base::Histogram* message_histogram_; // A null terminated list which creates an incoming_queue of tasks that are // acquired under a mutex for processing on this instance's thread. These @@ -476,6 +487,9 @@ class MessageLoop : public base::MessagePump::Delegate { #if defined(OS_WIN) base::TimeTicks high_resolution_timer_expiration_; + // Should be set to true before calling Windows APIs like TrackPopupMenu, etc + // which enter a modal message loop. + bool os_modal_loop_; #endif // The next sequence number to use for delayed tasks. @@ -483,6 +497,7 @@ class MessageLoop : public base::MessagePump::Delegate { ObserverList<TaskObserver> task_observers_; + private: DISALLOW_COPY_AND_ASSIGN(MessageLoop); }; @@ -493,7 +508,7 @@ class MessageLoop : public base::MessagePump::Delegate { // This class is typically used like so: // MessageLoopForUI::current()->...call some method... // -class MessageLoopForUI : public MessageLoop { +class BASE_API MessageLoopForUI : public MessageLoop { public: MessageLoopForUI() : MessageLoop(TYPE_UI) { } @@ -549,7 +564,7 @@ COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI), // This class is typically used like so: // MessageLoopForIO::current()->...call some method... // -class MessageLoopForIO : public MessageLoop { +class BASE_API MessageLoopForIO : public MessageLoop { public: #if defined(OS_WIN) typedef base::MessagePumpForIO::IOHandler IOHandler; diff --git a/base/message_loop_proxy.h b/base/message_loop_proxy.h index 6a8cbe8..07bca64 100644 --- a/base/message_loop_proxy.h +++ b/base/message_loop_proxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,8 +6,9 @@ #define BASE_MESSAGE_LOOP_PROXY_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/task.h" namespace base { @@ -18,7 +19,7 @@ struct MessageLoopProxyTraits; // of a message loop. This class can outlive the target message loop. You can // obtain a MessageLoopProxy via Thread::message_loop_proxy() or // MessageLoopProxy::CreateForCurrentThread(). -class MessageLoopProxy +class BASE_API MessageLoopProxy : public base::RefCountedThreadSafe<MessageLoopProxy, MessageLoopProxyTraits> { public: @@ -26,8 +27,10 @@ class MessageLoopProxy // either post the Task to the MessageLoop (if it's still alive), or to // delete the Task otherwise. // They return true iff the thread existed and the task was posted. Note that - // even if the task is posted, there's no guarantee that it will run, since - // the target thread may already have a Quit message in its queue. + // even if the task is posted, there's no guarantee that it will run; for + // example the target loop may already be quitting, or in the case of a + // delayed task a Quit message may preempt it in the message loop queue. + // Conversely, a return value of false is a guarantee the task will not run. virtual bool PostTask(const tracked_objects::Location& from_here, Task* task) = 0; virtual bool PostDelayedTask(const tracked_objects::Location& from_here, @@ -58,6 +61,7 @@ class MessageLoopProxy static scoped_refptr<MessageLoopProxy> CreateForCurrentThread(); protected: + friend class RefCountedThreadSafe<MessageLoopProxy, MessageLoopProxyTraits>; friend struct MessageLoopProxyTraits; MessageLoopProxy(); diff --git a/base/message_loop_proxy_impl.h b/base/message_loop_proxy_impl.h index 03e0271..80d9a26 100644 --- a/base/message_loop_proxy_impl.h +++ b/base/message_loop_proxy_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #define BASE_MESSAGE_LOOP_PROXY_IMPL_H_ #pragma once +#include "base/base_api.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/synchronization/lock.h" @@ -15,8 +16,8 @@ namespace base { // A stock implementation of MessageLoopProxy that takes in a MessageLoop // and keeps track of its lifetime using the MessageLoop DestructionObserver. // For now a MessageLoopProxyImpl can only be created for the current thread. -class MessageLoopProxyImpl : public MessageLoopProxy, - public MessageLoop::DestructionObserver { +class BASE_API MessageLoopProxyImpl : public MessageLoopProxy, + public MessageLoop::DestructionObserver { public: virtual ~MessageLoopProxyImpl(); diff --git a/base/message_loop_proxy_impl_unittest.cc b/base/message_loop_proxy_impl_unittest.cc index 61c7850..558cd93 100644 --- a/base/message_loop_proxy_impl_unittest.cc +++ b/base/message_loop_proxy_impl_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "base/message_loop_proxy_impl.h" -#include "base/scoped_ptr.h" #include "base/threading/thread.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc index 2869bb8..cd681f3 100644 --- a/base/message_loop_unittest.cc +++ b/base/message_loop_unittest.cc @@ -6,8 +6,8 @@ #include "base/eintr_wrapper.h" #include "base/logging.h" +#include "base/memory/ref_counted.h" #include "base/message_loop.h" -#include "base/ref_counted.h" #include "base/task.h" #include "base/threading/platform_thread.h" #include "base/threading/thread.h" diff --git a/base/message_pump.h b/base/message_pump.h index 866b33a..6a48e81 100644 --- a/base/message_pump.h +++ b/base/message_pump.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,17 +6,18 @@ #define BASE_MESSAGE_PUMP_H_ #pragma once -#include "base/ref_counted.h" +#include "base/base_api.h" +#include "base/memory/ref_counted.h" namespace base { class TimeTicks; -class MessagePump : public RefCountedThreadSafe<MessagePump> { +class BASE_API MessagePump : public RefCountedThreadSafe<MessagePump> { public: // Please see the comments above the Run method for an illustration of how // these delegate methods are used. - class Delegate { + class BASE_API Delegate { public: virtual ~Delegate() {} diff --git a/base/message_pump_glib.h b/base/message_pump_glib.h index 70bf108..7d7d8da 100644 --- a/base/message_pump_glib.h +++ b/base/message_pump_glib.h @@ -6,9 +6,9 @@ #define BASE_MESSAGE_PUMP_GLIB_H_ #pragma once +#include "base/memory/scoped_ptr.h" #include "base/message_pump.h" #include "base/observer_list.h" -#include "base/scoped_ptr.h" #include "base/time.h" typedef union _GdkEvent GdkEvent; diff --git a/base/message_pump_glib_unittest.cc b/base/message_pump_glib_unittest.cc index fc604b9..496fda6 100644 --- a/base/message_pump_glib_unittest.cc +++ b/base/message_pump_glib_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,8 +10,8 @@ #include <algorithm> #include <vector> +#include "base/memory/ref_counted.h" #include "base/message_loop.h" -#include "base/ref_counted.h" #include "base/threading/thread.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/message_pump_glib_x.cc b/base/message_pump_glib_x.cc index 06a156e..34313e5 100644 --- a/base/message_pump_glib_x.cc +++ b/base/message_pump_glib_x.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -79,8 +79,7 @@ namespace base { MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), #if defined(HAVE_XINPUT2) xiopcode_(-1), - masters_(), - slaves_(), + pointer_devices_(), #endif gdksource_(NULL), dispatching_event_(false), @@ -112,22 +111,17 @@ void MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) { XISetMask(mask, XI_ButtonRelease); XISetMask(mask, XI_Motion); - // It is necessary to select only for the master devices. XInput2 provides - // enough information to the event callback to decide which slave device - // triggered the event, thus decide whether the 'pointer event' is a 'mouse - // event' or a 'touch event'. So it is not necessary to select for the slave - // devices here. - XIEventMask evmasks[masters_.size()]; + XIEventMask evmasks[pointer_devices_.size()]; int count = 0; - for (std::set<int>::const_iterator iter = masters_.begin(); - iter != masters_.end(); + for (std::set<int>::const_iterator iter = pointer_devices_.begin(); + iter != pointer_devices_.end(); ++iter, ++count) { evmasks[count].deviceid = *iter; evmasks[count].mask_len = sizeof(mask); evmasks[count].mask = mask; } - XISelectEvents(xdisplay, xwindow, evmasks, masters_.size()); + XISelectEvents(xdisplay, xwindow, evmasks, pointer_devices_.size()); // TODO(sad): Setup masks for keyboard events. @@ -224,7 +218,8 @@ 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; + if (pump_x->gdksource_) + 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]) { @@ -289,22 +284,25 @@ void MessagePumpGlibX::InitializeXInput2(void) { SetupGtkWidgetRealizeNotifier(this); // Instead of asking X for the list of devices all the time, let's maintain a - // list of slave (physical) and master (virtual) pointer devices. + // list of pointer devices we care about. + // It is not necessary to select for slave devices. XInput2 provides enough + // information to the event callback to decide which slave device triggered + // the event, thus decide whether the 'pointer event' is a 'mouse event' or a + // 'touch event'. + // If the touch device has 'GrabDevice' set and 'SendCoreEvents' unset (which + // is possible), then the device is detected as a floating device, and a + // floating device is not connected to a master device. So it is necessary to + // also select on the floating devices. int count = 0; XIDeviceInfo* devices = XIQueryDevice(xdisplay, XIAllDevices, &count); for (int i = 0; i < count; i++) { XIDeviceInfo* devinfo = devices + i; - if (devinfo->use == XISlavePointer) { - slaves_.insert(devinfo->deviceid); - } else if (devinfo->use == XIMasterPointer) { - masters_.insert(devinfo->deviceid); - } - // We do not need to care about XIFloatingSlave, because the callback for - // XI_HierarchyChanged event will take care of it. + if (devinfo->use == XIFloatingSlave || devinfo->use == XIMasterPointer) + pointer_devices_.insert(devinfo->deviceid); } XIFreeDeviceInfo(devices); - // TODO(sad): Select on root for XI_HierarchyChanged so that slaves_ and + // TODO(sad): Select on root for XI_HierarchyChanged so that floats_ and // masters_ can be kept up-to-date. This is a relatively rare event, so we can // put it off for a later time. // Note: It is not necessary to listen for XI_DeviceChanged events. diff --git a/base/message_pump_glib_x.h b/base/message_pump_glib_x.h index e94b797..e8e92d6 100644 --- a/base/message_pump_glib_x.h +++ b/base/message_pump_glib_x.h @@ -48,13 +48,10 @@ class MessagePumpGlibX : public MessagePumpForUI { // The opcode used for checking events. int xiopcode_; - // The list of master pointer devices. We maintain this list so that it is not - // necessary to query X for the list of devices for each GdkWindow created. - std::set<int> masters_; - - // The list of slave (physical) pointer devices. - // TODO(sad): This is currently unused, and may be removed eventually. - std::set<int> slaves_; + // The list of pointer devices we care about. We maintain this list so that + // it is not necessary to query X for the list of devices for each + // GdkWindow created. + std::set<int> pointer_devices_; #endif // The event source for GDK events. diff --git a/base/message_pump_libevent.cc b/base/message_pump_libevent.cc index 28b4bfe..5154233 100644 --- a/base/message_pump_libevent.cc +++ b/base/message_pump_libevent.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,8 +11,8 @@ #include "base/eintr_wrapper.h" #include "base/logging.h" #include "base/mac/scoped_nsautorelease_pool.h" +#include "base/memory/scoped_ptr.h" #include "base/observer_list.h" -#include "base/scoped_ptr.h" #include "base/time.h" #if defined(USE_SYSTEM_LIBEVENT) #include <event.h> diff --git a/base/message_pump_mac.h b/base/message_pump_mac.h index b903a1a..08d6b83 100644 --- a/base/message_pump_mac.h +++ b/base/message_pump_mac.h @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -34,7 +34,6 @@ #include "base/message_pump.h" #include <CoreFoundation/CoreFoundation.h> -#include <IOKit/IOKitLib.h> #if !defined(__OBJC__) class NSAutoreleasePool; @@ -142,12 +141,6 @@ class MessagePumpCFRunLoopBase : public MessagePump { // the basis of run loops starting and stopping. virtual void EnterExitRunLoop(CFRunLoopActivity activity); - // IOKit power state change notification callback, called when the system - // enters and leaves the sleep state. - static void PowerStateNotification(void* info, io_service_t service, - uint32_t message_type, - void* message_argument); - // The thread's run loop. CFRunLoopRef run_loop_; @@ -161,11 +154,6 @@ class MessagePumpCFRunLoopBase : public MessagePump { CFRunLoopObserverRef pre_source_observer_; CFRunLoopObserverRef enter_exit_observer_; - // Objects used for power state notification. See PowerStateNotification. - io_connect_t root_power_domain_; - IONotificationPortRef power_notification_port_; - io_object_t power_notification_object_; - // (weak) Delegate passed as an argument to the innermost Run call. Delegate* delegate_; diff --git a/base/message_pump_mac.mm b/base/message_pump_mac.mm index 8feb56f..2a50b64 100644 --- a/base/message_pump_mac.mm +++ b/base/message_pump_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,8 +6,6 @@ #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> -#include <IOKit/IOMessage.h> -#include <IOKit/pwr_mgt/IOPMLib.h> #include <limits> @@ -116,33 +114,12 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() EnterExitObserver, &observer_context); CFRunLoopAddObserver(run_loop_, enter_exit_observer_, kCFRunLoopCommonModes); - - root_power_domain_ = IORegisterForSystemPower(this, - &power_notification_port_, - PowerStateNotification, - &power_notification_object_); - if (root_power_domain_ != MACH_PORT_NULL) { - CFRunLoopAddSource( - run_loop_, - IONotificationPortGetRunLoopSource(power_notification_port_), - kCFRunLoopCommonModes); - } } // Ideally called on the run loop thread. If other run loops were running // lower on the run loop thread's stack when this object was created, the // same number of run loops must be running when this object is destroyed. MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() { - if (root_power_domain_ != MACH_PORT_NULL) { - CFRunLoopRemoveSource( - run_loop_, - IONotificationPortGetRunLoopSource(power_notification_port_), - kCFRunLoopCommonModes); - IODeregisterForSystemPower(&power_notification_object_); - IOServiceClose(root_power_domain_); - IONotificationPortDestroy(power_notification_port_); - } - CFRunLoopRemoveObserver(run_loop_, enter_exit_observer_, kCFRunLoopCommonModes); CFRelease(enter_exit_observer_); @@ -465,73 +442,6 @@ void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, self->EnterExitRunLoop(activity); } -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::PowerStateNotification(void* info, - io_service_t service, - uint32_t message_type, - void* message_argument) { - // CFRunLoopTimer (NSTimer) is scheduled in terms of CFAbsoluteTime, which - // measures the number of seconds since 2001-01-01 00:00:00.0 Z. It is - // implemented in terms of kernel ticks, as in mach_absolute_time. While an - // offset and scale factor can be applied to convert between the two time - // bases at any time after boot, the kernel clock stops while the system is - // asleep, altering the offset. (The offset will also change when the - // real-time clock is adjusted.) CFRunLoopTimers are not readjusted to take - // this into account when the system wakes up, so any timers that were - // pending while the system was asleep will be delayed by the sleep - // duration. - // - // The MessagePump interface assumes that scheduled delayed work will be - // performed at the time ScheduleDelayedWork was asked to perform it. The - // delay caused by the CFRunLoopTimer not firing at the appropriate time - // results in a stall of queued delayed work when the system wakes up. - // With this limitation, scheduled work would not be performed until - // (system wake time + scheduled work time - system sleep time), while it - // would be expected to be performed at (scheduled work time). - // - // To work around this problem, when the system wakes up from sleep, if a - // delayed work timer is pending, it is rescheduled to fire at the original - // time that it was scheduled to fire. - // - // This mechanism is not resilient if the real-time clock does not maintain - // stable time while the system is sleeping, but it matches the behavior of - // the various other MessagePump implementations, and MessageLoop seems to - // be limited in the same way. - // - // References - // - Chris Kane, "NSTimer and deep sleep," cocoa-dev@lists.apple.com, - // http://lists.apple.com/archives/Cocoa-dev/2002/May/msg01547.html - // - Apple Technical Q&A QA1340, "Registering and unregistering for sleep - // and wake notifications," - // http://developer.apple.com/mac/library/qa/qa2004/qa1340.html - // - Core Foundation source code, CF-550/CFRunLoop.c and CF-550/CFDate.c, - // http://www.opensource.apple.com/ - - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - - switch (message_type) { - case kIOMessageSystemWillPowerOn: - if (self->delayed_work_fire_time_ != kCFTimeIntervalMax) { - CFRunLoopTimerSetNextFireDate(self->delayed_work_timer_, - self->delayed_work_fire_time_); - } - break; - - case kIOMessageSystemWillSleep: - case kIOMessageCanSystemSleep: - // The system will wait for 30 seconds before entering sleep if neither - // IOAllowPowerChange nor IOCancelPowerChange are called. That would be - // pretty antisocial. - IOAllowPowerChange(self->root_power_domain_, - reinterpret_cast<long>(message_argument)); - break; - - default: - break; - } -} - // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default // implementation is a no-op. void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) { diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc index 6098a4a..9d0ec53 100644 --- a/base/message_pump_win.cc +++ b/base/message_pump_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,9 @@ #include <math.h> +#include "base/message_loop.h" #include "base/metrics/histogram.h" +#include "base/win/wrapped_window_proc.h" namespace base { @@ -121,7 +123,7 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { delayed_work_time_ = delayed_work_time; int delay_msec = GetCurrentDelay(); - DCHECK(delay_msec >= 0); + DCHECK_GE(delay_msec, 0); if (delay_msec < USER_TIMER_MINIMUM) delay_msec = USER_TIMER_MINIMUM; @@ -232,7 +234,7 @@ void MessagePumpForUI::InitMessageWnd() { WNDCLASSEX wc = {0}; wc.cbSize = sizeof(wc); - wc.lpfnWndProc = WndProcThunk; + wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>; wc.hInstance = hinst; wc.lpszClassName = kWndClass; RegisterClassEx(&wc); @@ -370,8 +372,19 @@ bool MessagePumpForUI::ProcessPumpReplacementMessage() { // possibly be posted), and finally dispatches that peeked replacement. Note // that the re-post of kMsgHaveWork may be asynchronous to this thread!! + bool have_message = false; MSG msg; - bool have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)); + // We should not process all window messages if we are in the context of an + // OS modal loop, i.e. in the context of a windows API call like MessageBox. + // This is to ensure that these messages are peeked out by the OS modal loop. + if (MessageLoop::current()->os_modal_loop()) { + // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above. + have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || + PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE); + } else { + have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)); + } + DCHECK(!have_message || kMsgHaveWork != msg.message || msg.hwnd != message_hwnd_); diff --git a/base/message_pump_win.h b/base/message_pump_win.h index af97530..5642220 100644 --- a/base/message_pump_win.h +++ b/base/message_pump_win.h @@ -10,6 +10,7 @@ #include <list> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/message_pump.h" #include "base/observer_list.h" @@ -21,7 +22,7 @@ namespace base { // MessagePumpWin serves as the base for specialized versions of the MessagePump // for Windows. It provides basic functionality like handling of observers and // controlling the lifetime of the message pump. -class MessagePumpWin : public MessagePump { +class BASE_API MessagePumpWin : public MessagePump { public: // An Observer is an object that receives global notifications from the // UI MessageLoop. @@ -156,7 +157,7 @@ class MessagePumpWin : public MessagePump { // an excellent choice. It is also helpful that the starter messages that are // placed in the queue when new task arrive also awakens DoRunLoop. // -class MessagePumpForUI : public MessagePumpWin { +class BASE_API MessagePumpForUI : public MessagePumpWin { public: // The application-defined code passed to the hook procedure. static const int kMessageFilterCode = 0x5001; @@ -195,7 +196,7 @@ class MessagePumpForUI : public MessagePumpWin { // deal with Windows mesagges, and instead has a Run loop based on Completion // Ports so it is better suited for IO operations. // -class MessagePumpForIO : public MessagePumpWin { +class BASE_API MessagePumpForIO : public MessagePumpWin { public: struct IOContext; diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h index 8b4a606..dcfd391 100644 --- a/base/metrics/field_trial.h +++ b/base/metrics/field_trial.h @@ -30,32 +30,44 @@ // Somewhere in main thread initialization code, we'd probably define an // instance of a FieldTrial, with code such as: -// // Note, FieldTrials are reference counted, and persist automagically until +// // FieldTrials are reference counted, and persist automagically until // // process teardown, courtesy of their automatic registration in // // FieldTrialList. -// scoped_refptr<FieldTrial> trial = new FieldTrial("MemoryExperiment", 1000); -// int group1 = trial->AppendGroup("high_mem", 20); // 2% in high_mem group. -// int group2 = trial->AppendGroup("low_mem", 20); // 2% in low_mem group. +// // Note: This field trial will run in Chrome instances compiled through +// // 8 July, 2015, and after that all instances will be in "StandardMem". +// scoped_refptr<FieldTrial> trial = new FieldTrial("MemoryExperiment", 1000, +// "StandardMem", 2015, 7, 8); +// const int kHighMemGroup = +// trial->AppendGroup("HighMem", 20); // 2% in HighMem group. +// const int kLowMemGroup = +// trial->AppendGroup("LowMem", 20); // 2% in LowMem group. // // Take action depending of which group we randomly land in. -// if (trial->group() == group1) +// if (trial->group() == kHighMemGroup) // SetPruningAlgorithm(kType1); // Sample setting of browser state. -// else if (trial->group() == group2) +// else if (trial->group() == kLowMemGroup) // SetPruningAlgorithm(kType2); // Sample alternate setting. -// We then modify any histograms we wish to correlate with our experiment to -// have slighly different names, depending on what group the trial instance -// happened (randomly) to be assigned to: +// We then, in addition to our original histogram, output histograms which have +// slightly different names depending on what group the trial instance happened +// to randomly be assigned: -// HISTOGRAM_COUNTS(FieldTrial::MakeName("Memory.RendererTotal", -// "MemoryExperiment").data(), count); +// HISTOGRAM_COUNTS("Memory.RendererTotal", count); // The original histogram. +// static bool use_memoryexperiment_histogram( +// base::FieldTrialList::Find("MemoryExperiment") && +// !base::FieldTrialList::Find("MemoryExperiment")->group_name().empty()); +// if (use_memoryexperiment_histogram) { +// HISTOGRAM_COUNTS(FieldTrial::MakeName("Memory.RendererTotal", +// "MemoryExperiment"), count); +// } -// The above code will create 3 distinct histograms, with each run of the +// The above code will create four distinct histograms, with each run of the // application being assigned to of of the three groups, and for each group, the // correspondingly named histogram will be populated: -// Memory.RendererTotal // 96% of users still fill this histogram. -// Memory.RendererTotal_high_mem // 2% of users will fill this histogram. -// Memory.RendererTotal_low_mem // 2% of users will fill this histogram. +// Memory.RendererTotal // 100% of users still fill this histogram. +// Memory.RendererTotal_HighMem // 2% of users will fill this histogram. +// Memory.RendererTotal_LowMem // 2% of users will fill this histogram. +// Memory.RendererTotal_StandardMem // 96% of users will fill this histogram. //------------------------------------------------------------------------------ @@ -66,8 +78,9 @@ #include <map> #include <string> +#include "base/base_api.h" #include "base/gtest_prod_util.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/time.h" @@ -75,7 +88,7 @@ namespace base { class FieldTrialList; -class FieldTrial : public RefCounted<FieldTrial> { +class BASE_API FieldTrial : public RefCounted<FieldTrial> { public: typedef int Probability; // Probability type for being selected in a trial. @@ -198,7 +211,7 @@ class FieldTrial : public RefCounted<FieldTrial> { // Class with a list of all active field trials. A trial is active if it has // been registered, which includes evaluating its state based on its probaility. // Only one instance of this class exists. -class FieldTrialList { +class BASE_API FieldTrialList { public: // Define a separator charactor to use when creating a persistent form of an // instance. This is intended for use as a command line argument, passed to a diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 1d6f884..4262853 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -73,9 +73,12 @@ typedef Histogram::Count Count; // static const size_t Histogram::kBucketCount_MAX = 16384u; -scoped_refptr<Histogram> Histogram::FactoryGet(const std::string& name, - Sample minimum, Sample maximum, size_t bucket_count, Flags flags) { - scoped_refptr<Histogram> histogram(NULL); +Histogram* Histogram::FactoryGet(const std::string& name, + Sample minimum, + Sample maximum, + size_t bucket_count, + Flags flags) { + Histogram* histogram(NULL); // Defensive code. if (minimum < 1) @@ -84,22 +87,28 @@ scoped_refptr<Histogram> Histogram::FactoryGet(const std::string& name, maximum = kSampleType_MAX - 1; if (!StatisticsRecorder::FindHistogram(name, &histogram)) { - histogram = new Histogram(name, minimum, maximum, bucket_count); - histogram->InitializeBucketRange(); - StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); + // Extra variable is not needed... but this keeps this section basically + // identical to other derived classes in this file (and compiler will + // optimize away the extra variable. + // To avoid racy destruction at shutdown, the following will be leaked. + Histogram* tentative_histogram = + new Histogram(name, minimum, maximum, bucket_count); + tentative_histogram->InitializeBucketRange(); + tentative_histogram->SetFlags(flags); + histogram = + StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); } DCHECK_EQ(HISTOGRAM, histogram->histogram_type()); DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); - histogram->SetFlags(flags); return histogram; } -scoped_refptr<Histogram> Histogram::FactoryTimeGet(const std::string& name, - TimeDelta minimum, - TimeDelta maximum, - size_t bucket_count, - Flags flags) { +Histogram* Histogram::FactoryTimeGet(const std::string& name, + TimeDelta minimum, + TimeDelta maximum, + size_t bucket_count, + Flags flags) { return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), bucket_count, flags); } @@ -259,7 +268,7 @@ bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) { DCHECK_NE(NOT_VALID_IN_RENDERER, histogram_type); - scoped_refptr<Histogram> render_histogram(NULL); + Histogram* render_histogram(NULL); if (histogram_type == HISTOGRAM) { render_histogram = Histogram::FactoryGet( @@ -610,13 +619,8 @@ void Histogram::WriteAsciiHeader(const SampleSet& snapshot, DCHECK_EQ(snapshot.sum(), 0); } else { double average = static_cast<float>(snapshot.sum()) / sample_count; - double variance = static_cast<float>(snapshot.square_sum())/sample_count - - average * average; - double standard_deviation = sqrt(variance); - StringAppendF(output, - ", average = %.1f, standard deviation = %.1f", - average, standard_deviation); + StringAppendF(output, ", average = %.1f", average); } if (flags_ & ~kHexRangePrintingFlag) StringAppendF(output, " (flags = 0x%x)", flags_ & ~kHexRangePrintingFlag); @@ -661,7 +665,6 @@ void Histogram::WriteAsciiBucketGraph(double current_size, double max_size, Histogram::SampleSet::SampleSet() : counts_(), sum_(0), - square_sum_(0), redundant_count_(0) { } @@ -682,11 +685,9 @@ void Histogram::SampleSet::Accumulate(Sample value, Count count, DCHECK(count == 1 || count == -1); counts_[index] += count; sum_ += count * value; - square_sum_ += (count * value) * static_cast<int64>(value); redundant_count_ += count; DCHECK_GE(counts_[index], 0); DCHECK_GE(sum_, 0); - DCHECK_GE(square_sum_, 0); DCHECK_GE(redundant_count_, 0); } @@ -703,7 +704,6 @@ Count Histogram::SampleSet::TotalCount() const { void Histogram::SampleSet::Add(const SampleSet& other) { DCHECK_EQ(counts_.size(), other.counts_.size()); sum_ += other.sum_; - square_sum_ += other.square_sum_; redundant_count_ += other.redundant_count_; for (size_t index = 0; index < counts_.size(); ++index) counts_[index] += other.counts_[index]; @@ -711,11 +711,10 @@ void Histogram::SampleSet::Add(const SampleSet& other) { void Histogram::SampleSet::Subtract(const SampleSet& other) { DCHECK_EQ(counts_.size(), other.counts_.size()); - // Note: Race conditions in snapshotting a sum or square_sum may lead to - // (temporary) negative values when snapshots are later combined (and deltas - // calculated). As a result, we don't currently CHCEK() for positive values. + // Note: Race conditions in snapshotting a sum may lead to (temporary) + // negative values when snapshots are later combined (and deltas calculated). + // As a result, we don't currently CHCEK() for positive values. sum_ -= other.sum_; - square_sum_ -= other.square_sum_; redundant_count_ -= other.redundant_count_; for (size_t index = 0; index < counts_.size(); ++index) { counts_[index] -= other.counts_[index]; @@ -725,7 +724,6 @@ void Histogram::SampleSet::Subtract(const SampleSet& other) { bool Histogram::SampleSet::Serialize(Pickle* pickle) const { pickle->WriteInt64(sum_); - pickle->WriteInt64(square_sum_); pickle->WriteInt64(redundant_count_); pickle->WriteSize(counts_.size()); @@ -739,13 +737,11 @@ bool Histogram::SampleSet::Serialize(Pickle* pickle) const { bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) { DCHECK_EQ(counts_.size(), 0u); DCHECK_EQ(sum_, 0); - DCHECK_EQ(square_sum_, 0); DCHECK_EQ(redundant_count_, 0); size_t counts_size; if (!pickle.ReadInt64(iter, &sum_) || - !pickle.ReadInt64(iter, &square_sum_) || !pickle.ReadInt64(iter, &redundant_count_) || !pickle.ReadSize(iter, &counts_size)) { return false; @@ -774,12 +770,12 @@ bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) { LinearHistogram::~LinearHistogram() { } -scoped_refptr<Histogram> LinearHistogram::FactoryGet(const std::string& name, - Sample minimum, - Sample maximum, - size_t bucket_count, - Flags flags) { - scoped_refptr<Histogram> histogram(NULL); +Histogram* LinearHistogram::FactoryGet(const std::string& name, + Sample minimum, + Sample maximum, + size_t bucket_count, + Flags flags) { + Histogram* histogram(NULL); if (minimum < 1) minimum = 1; @@ -787,25 +783,25 @@ scoped_refptr<Histogram> LinearHistogram::FactoryGet(const std::string& name, maximum = kSampleType_MAX - 1; if (!StatisticsRecorder::FindHistogram(name, &histogram)) { - LinearHistogram* linear_histogram = + // To avoid racy destruction at shutdown, the following will be leaked. + LinearHistogram* tentative_histogram = new LinearHistogram(name, minimum, maximum, bucket_count); - linear_histogram->InitializeBucketRange(); - histogram = linear_histogram; - StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); + tentative_histogram->InitializeBucketRange(); + tentative_histogram->SetFlags(flags); + histogram = + StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); } DCHECK_EQ(LINEAR_HISTOGRAM, histogram->histogram_type()); DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); - histogram->SetFlags(flags); return histogram; } -scoped_refptr<Histogram> LinearHistogram::FactoryTimeGet( - const std::string& name, - TimeDelta minimum, - TimeDelta maximum, - size_t bucket_count, - Flags flags) { +Histogram* LinearHistogram::FactoryTimeGet(const std::string& name, + TimeDelta minimum, + TimeDelta maximum, + size_t bucket_count, + Flags flags) { return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), bucket_count, flags); } @@ -875,19 +871,19 @@ bool LinearHistogram::PrintEmptyBucket(size_t index) const { // This section provides implementation for BooleanHistogram. //------------------------------------------------------------------------------ -scoped_refptr<Histogram> BooleanHistogram::FactoryGet(const std::string& name, - Flags flags) { - scoped_refptr<Histogram> histogram(NULL); +Histogram* BooleanHistogram::FactoryGet(const std::string& name, Flags flags) { + Histogram* histogram(NULL); if (!StatisticsRecorder::FindHistogram(name, &histogram)) { - BooleanHistogram* boolean_histogram = new BooleanHistogram(name); - boolean_histogram->InitializeBucketRange(); - histogram = boolean_histogram; - StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); + // To avoid racy destruction at shutdown, the following will be leaked. + BooleanHistogram* tentative_histogram = new BooleanHistogram(name); + tentative_histogram->InitializeBucketRange(); + tentative_histogram->SetFlags(flags); + histogram = + StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); } DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->histogram_type()); - histogram->SetFlags(flags); return histogram; } @@ -907,11 +903,10 @@ BooleanHistogram::BooleanHistogram(const std::string& name) // CustomHistogram: //------------------------------------------------------------------------------ -scoped_refptr<Histogram> CustomHistogram::FactoryGet( - const std::string& name, - const std::vector<Sample>& custom_ranges, - Flags flags) { - scoped_refptr<Histogram> histogram(NULL); +Histogram* CustomHistogram::FactoryGet(const std::string& name, + const std::vector<Sample>& custom_ranges, + Flags flags) { + Histogram* histogram(NULL); // Remove the duplicates in the custom ranges array. std::vector<int> ranges = custom_ranges; @@ -927,16 +922,17 @@ scoped_refptr<Histogram> CustomHistogram::FactoryGet( DCHECK_LT(ranges.back(), kSampleType_MAX); if (!StatisticsRecorder::FindHistogram(name, &histogram)) { - CustomHistogram* custom_histogram = new CustomHistogram(name, ranges); - custom_histogram->InitializedCustomBucketRange(ranges); - histogram = custom_histogram; - StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); + // To avoid racy destruction at shutdown, the following will be leaked. + CustomHistogram* tentative_histogram = new CustomHistogram(name, ranges); + tentative_histogram->InitializedCustomBucketRange(ranges); + tentative_histogram->SetFlags(flags); + histogram = + StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); } DCHECK_EQ(histogram->histogram_type(), CUSTOM_HISTOGRAM); DCHECK(histogram->HasConstructorArguments(ranges[1], ranges.back(), ranges.size())); - histogram->SetFlags(flags); return histogram; } @@ -1017,27 +1013,23 @@ bool StatisticsRecorder::IsActive() { return NULL != histograms_; } -// Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a -// reference, and we are called while in the Histogram constructor. In that -// scenario, a ref_ptr would have incremented the ref count when the histogram -// was passed to us, decremented it when we returned, and the instance would be -// destroyed before assignment (when value was returned by new). -// static -void StatisticsRecorder::RegisterOrDiscardDuplicate( - scoped_refptr<Histogram>* histogram) { - DCHECK((*histogram)->HasValidRangeChecksum()); +Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) { + DCHECK(histogram->HasValidRangeChecksum()); if (lock_ == NULL) - return; + return histogram; base::AutoLock auto_lock(*lock_); if (!histograms_) - return; - const std::string name = (*histogram)->histogram_name(); + return histogram; + const std::string name = histogram->histogram_name(); HistogramMap::iterator it = histograms_->find(name); // Avoid overwriting a previous registration. - if (histograms_->end() == it) - (*histograms_)[name] = *histogram; - else - *histogram = it->second; + if (histograms_->end() == it) { + (*histograms_)[name] = histogram; + } else { + delete histogram; // We already have one by this name. + histogram = it->second; + } + return histogram; } // static @@ -1100,7 +1092,7 @@ void StatisticsRecorder::GetHistograms(Histograms* output) { } bool StatisticsRecorder::FindHistogram(const std::string& name, - scoped_refptr<Histogram>* histogram) { + Histogram** histogram) { if (lock_ == NULL) return false; base::AutoLock auto_lock(*lock_); diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h index 347932a..bc58ee5 100644 --- a/base/metrics/histogram.h +++ b/base/metrics/histogram.h @@ -28,6 +28,15 @@ // at the low end of the histogram scale, but allows the histogram to cover a // gigantic range with the addition of very few buckets. +// Histograms use a pattern involving a function static variable, that is a +// pointer to a histogram. This static is explicitly initialized on any thread +// that detects a uninitialized (NULL) pointer. The potentially racy +// initialization is not a problem as it is always set to point to the same +// value (i.e., the FactoryGet always returns the same value). FactoryGet +// is also completely thread safe, which results in a completely thread safe, +// and relatively fast, set of counters. To avoid races at shutdown, the static +// pointer is NOT deleted, and we leak the histograms at process termination. + #ifndef BASE_METRICS_HISTOGRAM_H_ #define BASE_METRICS_HISTOGRAM_H_ #pragma once @@ -36,8 +45,8 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/gtest_prod_util.h" -#include "base/ref_counted.h" #include "base/logging.h" #include "base/time.h" @@ -65,11 +74,12 @@ class Lock; name, sample, 1, 10000, 50) #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::Histogram::FactoryGet(name, min, max, bucket_count, \ - base::Histogram::kNoFlags); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ + base::Histogram::kNoFlags); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->Add(sample); \ + counter->Add(sample); \ } while (0) #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ @@ -78,40 +88,43 @@ class Lock; // For folks that need real specific times, use this to select a precise range // of times you want plotted, and the number of buckets you want used. #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ - base::Histogram::kNoFlags); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ + base::Histogram::kNoFlags); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->AddTime(sample); \ + counter->AddTime(sample); \ } while (0) // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ - base::Histogram::kNoFlags); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ + base::Histogram::kNoFlags); \ DCHECK_EQ(name, counter->histogram_name()); \ - if ((sample) < (max) && counter.get()) counter->AddTime(sample); \ + if ((sample) < (max)) counter->AddTime(sample); \ } while (0) // Support histograming of an enumerated value. The samples should always be // less than boundary_value. #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ - boundary_value + 1, \ - base::Histogram::kNoFlags); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ + boundary_value + 1, base::Histogram::kNoFlags); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->Add(sample); \ + counter->Add(sample); \ } while (0) #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::CustomHistogram::FactoryGet(name, custom_ranges, \ - base::Histogram::kNoFlags); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ + base::Histogram::kNoFlags); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->Add(sample); \ + counter->Add(sample); \ } while (0) @@ -171,20 +184,22 @@ class Lock; base::TimeDelta::FromHours(1), 50) #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ base::Histogram::kUmaTargetedHistogramFlag); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->AddTime(sample); \ + counter->AddTime(sample); \ } while (0) // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ - base::Histogram::kUmaTargetedHistogramFlag); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ + base::Histogram::kUmaTargetedHistogramFlag); \ DCHECK_EQ(name, counter->histogram_name()); \ - if ((sample) < (max) && counter.get()) counter->AddTime(sample); \ + if ((sample) < (max)) counter->AddTime(sample); \ } while (0) #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ @@ -197,11 +212,12 @@ class Lock; name, sample, 1, 10000, 50) #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::Histogram::FactoryGet(name, min, max, bucket_count, \ - base::Histogram::kUmaTargetedHistogramFlag); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ + base::Histogram::kUmaTargetedHistogramFlag); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->Add(sample); \ + counter->Add(sample); \ } while (0) #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ @@ -213,20 +229,31 @@ class Lock; #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) +#define UMA_HISTOGRAM_BOOLEAN(name, sample) do { \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::BooleanHistogram::FactoryGet(name, \ + base::Histogram::kUmaTargetedHistogramFlag); \ + DCHECK_EQ(name, counter->histogram_name()); \ + counter->AddBoolean(sample); \ + } while (0) + #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ - boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ + boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->Add(sample); \ + counter->Add(sample); \ } while (0) #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ - static scoped_refptr<base::Histogram> counter = \ - base::CustomHistogram::FactoryGet(name, custom_ranges, \ - base::Histogram::kUmaTargetedHistogramFlag); \ + static base::Histogram* counter(NULL); \ + if (!counter) \ + counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ + base::Histogram::kUmaTargetedHistogramFlag); \ DCHECK_EQ(name, counter->histogram_name()); \ - if (counter.get()) counter->Add(sample); \ + counter->Add(sample); \ } while (0) //------------------------------------------------------------------------------ @@ -236,7 +263,7 @@ class CustomHistogram; class Histogram; class LinearHistogram; -class Histogram : public base::RefCountedThreadSafe<Histogram> { +class BASE_API Histogram { public: typedef int Sample; // Used for samples (and ranges of samples). typedef int Count; // Used to count samples in a bucket. @@ -295,7 +322,7 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> { //---------------------------------------------------------------------------- // Statistic values, developed over the life of the histogram. - class SampleSet { + class BASE_API SampleSet { public: explicit SampleSet(); ~SampleSet(); @@ -311,7 +338,6 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> { Count counts(size_t i) const { return counts_[i]; } Count TotalCount() const; int64 sum() const { return sum_; } - int64 square_sum() const { return square_sum_; } int64 redundant_count() const { return redundant_count_; } // Arithmetic manipulation of corresponding elements of the set. @@ -329,7 +355,6 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> { // Save simple stats locally. Note that this MIGHT get done in base class // without shared memory at some point. int64 sum_; // sum of samples. - int64 square_sum_; // sum of squares of samples. private: // Allow tests to corrupt our innards for testing purposes. @@ -348,11 +373,16 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> { //---------------------------------------------------------------------------- // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit // default underflow bucket. - static scoped_refptr<Histogram> FactoryGet(const std::string& name, - Sample minimum, Sample maximum, size_t bucket_count, Flags flags); - static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name, - base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, - Flags flags); + static Histogram* FactoryGet(const std::string& name, + Sample minimum, + Sample maximum, + size_t bucket_count, + Flags flags); + static Histogram* FactoryTimeGet(const std::string& name, + base::TimeDelta minimum, + base::TimeDelta maximum, + size_t bucket_count, + Flags flags); void Add(int value); @@ -427,7 +457,6 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> { bool HasValidRangeChecksum() const; protected: - friend class base::RefCountedThreadSafe<Histogram>; Histogram(const std::string& name, Sample minimum, Sample maximum, size_t bucket_count); Histogram(const std::string& name, TimeDelta minimum, @@ -481,6 +510,8 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> { FRIEND_TEST(HistogramTest, Crc32SampleHash); FRIEND_TEST(HistogramTest, Crc32TableTest); + friend class StatisticsRecorder; // To allow it to delete duplicates. + // Post constructor initialization. void Initialize(); @@ -550,17 +581,22 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> { // LinearHistogram is a more traditional histogram, with evenly spaced // buckets. -class LinearHistogram : public Histogram { +class BASE_API LinearHistogram : public Histogram { public: virtual ~LinearHistogram(); /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit default underflow bucket. */ - static scoped_refptr<Histogram> FactoryGet(const std::string& name, - Sample minimum, Sample maximum, size_t bucket_count, Flags flags); - static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name, - TimeDelta minimum, TimeDelta maximum, size_t bucket_count, - Flags flags); + static Histogram* FactoryGet(const std::string& name, + Sample minimum, + Sample maximum, + size_t bucket_count, + Flags flags); + static Histogram* FactoryTimeGet(const std::string& name, + TimeDelta minimum, + TimeDelta maximum, + size_t bucket_count, + Flags flags); // Overridden from Histogram: virtual ClassType histogram_type() const; @@ -601,10 +637,9 @@ class LinearHistogram : public Histogram { //------------------------------------------------------------------------------ // BooleanHistogram is a histogram for booleans. -class BooleanHistogram : public LinearHistogram { +class BASE_API BooleanHistogram : public LinearHistogram { public: - static scoped_refptr<Histogram> FactoryGet(const std::string& name, - Flags flags); + static Histogram* FactoryGet(const std::string& name, Flags flags); virtual ClassType histogram_type() const; @@ -619,11 +654,12 @@ class BooleanHistogram : public LinearHistogram { //------------------------------------------------------------------------------ // CustomHistogram is a histogram for a set of custom integers. -class CustomHistogram : public Histogram { +class BASE_API CustomHistogram : public Histogram { public: - static scoped_refptr<Histogram> FactoryGet(const std::string& name, - const std::vector<Sample>& custom_ranges, Flags flags); + static Histogram* FactoryGet(const std::string& name, + const std::vector<Sample>& custom_ranges, + Flags flags); // Overridden from Histogram: virtual ClassType histogram_type() const; @@ -644,9 +680,9 @@ class CustomHistogram : public Histogram { // general place for histograms to register, and supports a global API for // accessing (i.e., dumping, or graphing) the data in all the histograms. -class StatisticsRecorder { +class BASE_API StatisticsRecorder { public: - typedef std::vector<scoped_refptr<Histogram> > Histograms; + typedef std::vector<Histogram*> Histograms; StatisticsRecorder(); @@ -657,9 +693,9 @@ class StatisticsRecorder { // Register, or add a new histogram to the collection of statistics. If an // identically named histogram is already registered, then the argument - // |histogram| will be replaced by the previously registered value, discarding - // the referenced argument. - static void RegisterOrDiscardDuplicate(scoped_refptr<Histogram>* histogram); + // |histogram| will deleted. The returned value is always the registered + // histogram (either the argument, or the pre-existing registered histogram). + static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram); // Methods for printing histograms. Only histograms which have query as // a substring are written to output (an empty string will process all @@ -673,8 +709,7 @@ class StatisticsRecorder { // Find a histogram by name. It matches the exact name. This method is thread // safe. If a matching histogram is not found, then the |histogram| is // not changed. - static bool FindHistogram(const std::string& query, - scoped_refptr<Histogram>* histogram); + static bool FindHistogram(const std::string& query, Histogram** histogram); static bool dump_on_exit() { return dump_on_exit_; } @@ -689,7 +724,7 @@ class StatisticsRecorder { private: // We keep all registered histograms in a map, from name to histogram. - typedef std::map<std::string, scoped_refptr<Histogram> > HistogramMap; + typedef std::map<std::string, Histogram*> HistogramMap; static HistogramMap* histograms_; diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc index afa69a6..496ff63 100644 --- a/base/metrics/histogram_unittest.cc +++ b/base/metrics/histogram_unittest.cc @@ -1,10 +1,11 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Test of Histogram class #include "base/metrics/histogram.h" +#include "base/scoped_ptr.h" #include "base/time.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,15 +18,22 @@ class HistogramTest : public testing::Test { // Check for basic syntax and use. TEST(HistogramTest, StartupShutdownTest) { // Try basic construction - scoped_refptr<Histogram> histogram = Histogram::FactoryGet( - "TestHistogram", 1, 1000, 10, Histogram::kNoFlags); - scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet( - "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags); - - scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( - "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags); - scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet( - "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags); + Histogram* histogram(Histogram::FactoryGet( + "TestHistogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), histogram); + Histogram* histogram1(Histogram::FactoryGet( + "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), histogram1); + EXPECT_NE(histogram, histogram1); + + + Histogram* linear_histogram(LinearHistogram::FactoryGet( + "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), linear_histogram); + Histogram* linear_histogram1(LinearHistogram::FactoryGet( + "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), linear_histogram1); + EXPECT_NE(linear_histogram, linear_histogram1); std::vector<int> custom_ranges; custom_ranges.push_back(1); @@ -33,10 +41,12 @@ TEST(HistogramTest, StartupShutdownTest) { custom_ranges.push_back(10); custom_ranges.push_back(20); custom_ranges.push_back(30); - scoped_refptr<Histogram> custom_histogram = CustomHistogram::FactoryGet( - "TestCustomHistogram", custom_ranges, Histogram::kNoFlags); - scoped_refptr<Histogram> custom_histogram1 = CustomHistogram::FactoryGet( - "Test1CustomHistogram", custom_ranges, Histogram::kNoFlags); + Histogram* custom_histogram(CustomHistogram::FactoryGet( + "TestCustomHistogram", custom_ranges, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), custom_histogram); + Histogram* custom_histogram1(CustomHistogram::FactoryGet( + "Test1CustomHistogram", custom_ranges, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), custom_histogram1); // Use standard macros (but with fixed samples) HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1)); @@ -70,25 +80,29 @@ TEST(HistogramTest, RecordedStartupTest) { EXPECT_EQ(0U, histograms.size()); // Try basic construction - scoped_refptr<Histogram> histogram = Histogram::FactoryGet( - "TestHistogram", 1, 1000, 10, Histogram::kNoFlags); + Histogram* histogram(Histogram::FactoryGet( + "TestHistogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), histogram); histograms.clear(); StatisticsRecorder::GetHistograms(&histograms); // Load up lists EXPECT_EQ(1U, histograms.size()); - scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet( - "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags); + Histogram* histogram1(Histogram::FactoryGet( + "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), histogram1); histograms.clear(); StatisticsRecorder::GetHistograms(&histograms); // Load up lists EXPECT_EQ(2U, histograms.size()); - scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( - "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags); + Histogram* linear_histogram(LinearHistogram::FactoryGet( + "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), linear_histogram); histograms.clear(); StatisticsRecorder::GetHistograms(&histograms); // Load up lists EXPECT_EQ(3U, histograms.size()); - scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet( - "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags); + Histogram* linear_histogram1(LinearHistogram::FactoryGet( + "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), linear_histogram1); histograms.clear(); StatisticsRecorder::GetHistograms(&histograms); // Load up lists EXPECT_EQ(4U, histograms.size()); @@ -99,10 +113,12 @@ TEST(HistogramTest, RecordedStartupTest) { custom_ranges.push_back(10); custom_ranges.push_back(20); custom_ranges.push_back(30); - scoped_refptr<Histogram> custom_histogram = CustomHistogram::FactoryGet( - "TestCustomHistogram", custom_ranges, Histogram::kNoFlags); - scoped_refptr<Histogram> custom_histogram1 = CustomHistogram::FactoryGet( - "TestCustomHistogram", custom_ranges, Histogram::kNoFlags); + Histogram* custom_histogram(CustomHistogram::FactoryGet( + "TestCustomHistogram", custom_ranges, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), custom_histogram); + Histogram* custom_histogram1(CustomHistogram::FactoryGet( + "TestCustomHistogram", custom_ranges, Histogram::kNoFlags)); + EXPECT_NE(reinterpret_cast<Histogram*>(NULL), custom_histogram1); histograms.clear(); StatisticsRecorder::GetHistograms(&histograms); // Load up lists @@ -138,8 +154,8 @@ TEST(HistogramTest, RangeTest) { recorder.GetHistograms(&histograms); EXPECT_EQ(0U, histograms.size()); - scoped_refptr<Histogram> histogram = Histogram::FactoryGet( - "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. + Histogram* histogram(Histogram::FactoryGet( + "Histogram", 1, 64, 8, Histogram::kNoFlags)); // As per header file. // Check that we got a nice exponential when there was enough rooom. EXPECT_EQ(0, histogram->ranges(0)); int power_of_2 = 1; @@ -149,31 +165,30 @@ TEST(HistogramTest, RangeTest) { } EXPECT_EQ(INT_MAX, histogram->ranges(8)); - scoped_refptr<Histogram> short_histogram = Histogram::FactoryGet( - "Histogram Shortened", 1, 7, 8, Histogram::kNoFlags); + Histogram* short_histogram(Histogram::FactoryGet( + "Histogram Shortened", 1, 7, 8, Histogram::kNoFlags)); // Check that when the number of buckets is short, we get a linear histogram // for lack of space to do otherwise. for (int i = 0; i < 8; i++) EXPECT_EQ(i, short_histogram->ranges(i)); EXPECT_EQ(INT_MAX, short_histogram->ranges(8)); - scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( - "Linear", 1, 7, 8, Histogram::kNoFlags); + Histogram* linear_histogram(LinearHistogram::FactoryGet( + "Linear", 1, 7, 8, Histogram::kNoFlags)); // We also get a nice linear set of bucket ranges when we ask for it for (int i = 0; i < 8; i++) EXPECT_EQ(i, linear_histogram->ranges(i)); EXPECT_EQ(INT_MAX, linear_histogram->ranges(8)); - scoped_refptr<Histogram> linear_broad_histogram = LinearHistogram::FactoryGet( - "Linear widened", 2, 14, 8, Histogram::kNoFlags); + Histogram* linear_broad_histogram(LinearHistogram::FactoryGet( + "Linear widened", 2, 14, 8, Histogram::kNoFlags)); // ...but when the list has more space, then the ranges naturally spread out. for (int i = 0; i < 8; i++) EXPECT_EQ(2 * i, linear_broad_histogram->ranges(i)); EXPECT_EQ(INT_MAX, linear_broad_histogram->ranges(8)); - scoped_refptr<Histogram> transitioning_histogram = - Histogram::FactoryGet("LinearAndExponential", 1, 32, 15, - Histogram::kNoFlags); + Histogram* transitioning_histogram(Histogram::FactoryGet( + "LinearAndExponential", 1, 32, 15, Histogram::kNoFlags)); // When space is a little tight, we transition from linear to exponential. EXPECT_EQ(0, transitioning_histogram->ranges(0)); EXPECT_EQ(1, transitioning_histogram->ranges(1)); @@ -198,8 +213,8 @@ TEST(HistogramTest, RangeTest) { custom_ranges.push_back(10); custom_ranges.push_back(11); custom_ranges.push_back(300); - scoped_refptr<Histogram> test_custom_histogram = CustomHistogram::FactoryGet( - "TestCustomRangeHistogram", custom_ranges, Histogram::kNoFlags); + Histogram* test_custom_histogram(CustomHistogram::FactoryGet( + "TestCustomRangeHistogram", custom_ranges, Histogram::kNoFlags)); EXPECT_EQ(custom_ranges[0], test_custom_histogram->ranges(0)); EXPECT_EQ(custom_ranges[1], test_custom_histogram->ranges(1)); @@ -221,8 +236,8 @@ TEST(HistogramTest, CustomRangeTest) { custom_ranges.push_back(9); custom_ranges.push_back(10); custom_ranges.push_back(11); - scoped_refptr<Histogram> test_custom_histogram = CustomHistogram::FactoryGet( - "TestCustomRangeHistogram", custom_ranges, Histogram::kNoFlags); + Histogram* test_custom_histogram(CustomHistogram::FactoryGet( + "TestCustomRangeHistogram", custom_ranges, Histogram::kNoFlags)); EXPECT_EQ(0, test_custom_histogram->ranges(0)); // Auto added EXPECT_EQ(custom_ranges[0], test_custom_histogram->ranges(1)); @@ -242,8 +257,8 @@ TEST(HistogramTest, CustomRangeTest) { custom_ranges.push_back(0); // Push an explicit zero. custom_ranges.push_back(kBig); - scoped_refptr<Histogram> unsorted_histogram = CustomHistogram::FactoryGet( - "TestCustomUnsortedDupedHistogram", custom_ranges, Histogram::kNoFlags); + Histogram* unsorted_histogram(CustomHistogram::FactoryGet( + "TestCustomUnsortedDupedHistogram", custom_ranges, Histogram::kNoFlags)); EXPECT_EQ(0, unsorted_histogram->ranges(0)); EXPECT_EQ(kSmall, unsorted_histogram->ranges(1)); EXPECT_EQ(kMid, unsorted_histogram->ranges(2)); @@ -254,8 +269,8 @@ TEST(HistogramTest, CustomRangeTest) { // Make sure histogram handles out-of-bounds data gracefully. TEST(HistogramTest, BoundsTest) { const size_t kBucketCount = 50; - scoped_refptr<Histogram> histogram = Histogram::FactoryGet( - "Bounded", 10, 100, kBucketCount, Histogram::kNoFlags); + Histogram* histogram(Histogram::FactoryGet( + "Bounded", 10, 100, kBucketCount, Histogram::kNoFlags)); // Put two samples "out of bounds" above and below. histogram->Add(5); @@ -277,8 +292,8 @@ TEST(HistogramTest, BoundsTest) { // Check to be sure samples land as expected is "correct" buckets. TEST(HistogramTest, BucketPlacementTest) { - scoped_refptr<Histogram> histogram = Histogram::FactoryGet( - "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. + Histogram* histogram(Histogram::FactoryGet( + "Histogram", 1, 64, 8, Histogram::kNoFlags)); // As per header file. // Check that we got a nice exponential since there was enough rooom. EXPECT_EQ(0, histogram->ranges(0)); @@ -314,8 +329,8 @@ TEST(HistogramTest, BucketPlacementTest) { // out to the base namespace here. We need to be friends to corrupt the // internals of the histogram and/or sampleset. TEST(HistogramTest, CorruptSampleCounts) { - scoped_refptr<Histogram> histogram = Histogram::FactoryGet( - "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. + Histogram* histogram(Histogram::FactoryGet( + "Histogram", 1, 64, 8, Histogram::kNoFlags)); // As per header file. EXPECT_EQ(0, histogram->sample_.redundant_count()); histogram->Add(20); // Add some samples. @@ -339,8 +354,8 @@ TEST(HistogramTest, CorruptSampleCounts) { } TEST(HistogramTest, CorruptBucketBounds) { - scoped_refptr<Histogram> histogram = Histogram::FactoryGet( - "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. + Histogram* histogram(Histogram::FactoryGet( + "Histogram", 1, 64, 8, Histogram::kNoFlags)); // As per header file. Histogram::SampleSet snapshot; histogram->SnapshotSample(&snapshot); diff --git a/base/metrics/stats_counters.cc b/base/metrics/stats_counters.cc index 958f048..f763220 100644 --- a/base/metrics/stats_counters.cc +++ b/base/metrics/stats_counters.cc @@ -9,8 +9,12 @@ namespace base { StatsCounter::StatsCounter(const std::string& name) : counter_id_(-1) { // We prepend the name with 'c:' to indicate that it is a counter. - name_ = "c:"; - name_.append(name); + if (StatsTable::current()) { + // TODO(mbelshe): name_ construction is racy and it may corrupt memory for + // static. + name_ = "c:"; + name_.append(name); + } } StatsCounter::~StatsCounter() { @@ -61,8 +65,12 @@ int* StatsCounter::GetPtr() { StatsCounterTimer::StatsCounterTimer(const std::string& name) { // we prepend the name with 't:' to indicate that it is a timer. - name_ = "t:"; - name_.append(name); + if (StatsTable::current()) { + // TODO(mbelshe): name_ construction is racy and it may corrupt memory for + // static. + name_ = "t:"; + name_.append(name); + } } StatsCounterTimer::~StatsCounterTimer() { diff --git a/base/metrics/stats_counters.h b/base/metrics/stats_counters.h index 2de2b73..f40dcbe 100644 --- a/base/metrics/stats_counters.h +++ b/base/metrics/stats_counters.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,7 @@ #include <string> +#include "base/base_api.h" #include "base/metrics/stats_table.h" #include "base/time.h" @@ -46,14 +47,14 @@ namespace base { //------------------------------------------------------------------------------ // First provide generic macros, which exist in production as well as debug. #define STATS_COUNTER(name, delta) do { \ - static base::StatsCounter counter(name); \ + base::StatsCounter counter(name); \ counter.Add(delta); \ } while (0) #define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1) #define RATE_COUNTER(name, duration) do { \ - static base::StatsRate hit_count(name); \ + base::StatsRate hit_count(name); \ hit_count.AddTime(duration); \ } while (0) @@ -74,7 +75,7 @@ namespace base { //------------------------------------------------------------------------------ // StatsCounter represents a counter in the StatsTable class. -class StatsCounter { +class BASE_API StatsCounter { public: // Create a StatsCounter object. explicit StatsCounter(const std::string& name); @@ -128,7 +129,7 @@ class StatsCounter { // A StatsCounterTimer is a StatsCounter which keeps a timer during // the scope of the StatsCounterTimer. On destruction, it will record // its time measurement. -class StatsCounterTimer : protected StatsCounter { +class BASE_API StatsCounterTimer : protected StatsCounter { public: // Constructs and starts the timer. explicit StatsCounterTimer(const std::string& name); @@ -157,7 +158,7 @@ class StatsCounterTimer : protected StatsCounter { // A StatsRate is a timer that keeps a count of the number of intervals added so // that several statistics can be produced: // min, max, avg, count, total -class StatsRate : public StatsCounterTimer { +class BASE_API StatsRate : public StatsCounterTimer { public: // Constructs and starts the timer. explicit StatsRate(const std::string& name); diff --git a/base/metrics/stats_table.cc b/base/metrics/stats_table.cc index 0e8d016..488c690 100644 --- a/base/metrics/stats_table.cc +++ b/base/metrics/stats_table.cc @@ -5,8 +5,8 @@ #include "base/metrics/stats_table.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/process_util.h" -#include "base/scoped_ptr.h" #include "base/shared_memory.h" #include "base/string_piece.h" #include "base/string_util.h" diff --git a/base/metrics/stats_table.h b/base/metrics/stats_table.h index 94f7463..c8ebae7 100644 --- a/base/metrics/stats_table.h +++ b/base/metrics/stats_table.h @@ -23,6 +23,7 @@ #include <string> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/hash_tables.h" #include "base/synchronization/lock.h" @@ -30,7 +31,7 @@ namespace base { -class StatsTable { +class BASE_API StatsTable { public: // Create a new StatsTable. // If a StatsTable already exists with the specified name, this StatsTable diff --git a/base/mime_util_xdg.cc b/base/mime_util_xdg.cc index 4dd7a3e..e510b68 100644 --- a/base/mime_util_xdg.cc +++ b/base/mime_util_xdg.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -15,16 +15,21 @@ #include "base/file_util.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" #include "base/message_loop.h" -#include "base/scoped_ptr.h" -#include "base/singleton.h" #include "base/string_split.h" #include "base/string_util.h" +#include "base/synchronization/lock.h" #include "base/third_party/xdg_mime/xdgmime.h" #include "base/threading/thread_restrictions.h" namespace { +// None of the XDG stuff is thread-safe, so serialize all accesss under +// this lock. +base::Lock g_mime_util_xdg_lock; + class IconTheme; class MimeUtilConstants { @@ -553,11 +558,13 @@ namespace mime_util { std::string GetFileMimeType(const FilePath& filepath) { base::ThreadRestrictions::AssertIOAllowed(); + base::AutoLock scoped_lock(g_mime_util_xdg_lock); return xdg_mime_get_mime_type_from_file_name(filepath.value().c_str()); } std::string GetDataMimeType(const std::string& data) { base::ThreadRestrictions::AssertIOAllowed(); + base::AutoLock scoped_lock(g_mime_util_xdg_lock); return xdg_mime_get_mime_type_for_data(data.data(), data.length(), NULL); } @@ -585,8 +592,12 @@ FilePath GetMimeIcon(const std::string& mime_type, size_t size) { std::string icon_name; FilePath icon_file; - const char* icon = xdg_mime_get_icon(mime_type.c_str()); - icon_name = std::string(icon ? icon : ""); + { + base::AutoLock scoped_lock(g_mime_util_xdg_lock); + const char *icon = xdg_mime_get_icon(mime_type.c_str()); + icon_name = std::string(icon ? icon : ""); + } + if (icon_name.length()) icon_names.push_back(icon_name); diff --git a/base/native_library.h b/base/native_library.h index 6afd06d..2896163 100644 --- a/base/native_library.h +++ b/base/native_library.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,6 +9,7 @@ // This file defines a cross-platform "NativeLibrary" type which represents // a loadable module. +#include "base/base_api.h" #include "build/build_config.h" #if defined(OS_WIN) @@ -51,8 +52,11 @@ typedef void* NativeLibrary; #endif // OS_* // Loads a native library from disk. Release it with UnloadNativeLibrary when -// you're done. -NativeLibrary LoadNativeLibrary(const FilePath& library_path); +// you're done. Returns NULL on failure. +// If |err| is not NULL, it may be filled in with an error message on +// error. +BASE_API NativeLibrary LoadNativeLibrary(const FilePath& library_path, + std::string* error); #if defined(OS_WIN) // Loads a native library from disk. Release it with UnloadNativeLibrary when @@ -60,21 +64,22 @@ NativeLibrary LoadNativeLibrary(const FilePath& library_path); // This function retrieves the LoadLibrary function exported from kernel32.dll // and calls it instead of directly calling the LoadLibrary function via the // import table. -NativeLibrary LoadNativeLibraryDynamically(const FilePath& library_path); +BASE_API NativeLibrary LoadNativeLibraryDynamically( + const FilePath& library_path); #endif // OS_WIN // Unloads a native library. -void UnloadNativeLibrary(NativeLibrary library); +BASE_API void UnloadNativeLibrary(NativeLibrary library); // Gets a function pointer from a native library. -void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, - const char* name); +BASE_API void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, + const char* name); // Returns the full platform specific name for a native library. // For example: // "mylib" returns "mylib.dll" on Windows, "libmylib.so" on Linux, // "mylib.dylib" on Mac. -string16 GetNativeLibraryName(const string16& name); +BASE_API string16 GetNativeLibraryName(const string16& name); } // namespace base diff --git a/base/native_library_linux.cc b/base/native_library_linux.cc index e282bce..bcc4ffb 100644 --- a/base/native_library_linux.cc +++ b/base/native_library_linux.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -14,7 +14,8 @@ namespace base { // static -NativeLibrary LoadNativeLibrary(const FilePath& library_path) { +NativeLibrary LoadNativeLibrary(const FilePath& library_path, + std::string* error) { // dlopen() opens the file off disk. base::ThreadRestrictions::AssertIOAllowed(); @@ -23,16 +24,8 @@ NativeLibrary LoadNativeLibrary(const FilePath& library_path) { // http://crbug.com/17943, http://crbug.com/17557, http://crbug.com/36892, // and http://crbug.com/40794. void* dl = dlopen(library_path.value().c_str(), RTLD_LAZY); - if (!dl) { - std::string error_message = dlerror(); - // Some obsolete plugins depend on libxul or libxpcom. - // Ignore the error messages when failing to load these. - if (error_message.find("libxul.so") == std::string::npos && - error_message.find("libxpcom.so") == std::string::npos) { - LOG(ERROR) << "dlopen failed when trying to open " << library_path.value() - << ": " << error_message; - } - } + if (!dl && error) + *error = dlerror(); return dl; } diff --git a/base/native_library_mac.mm b/base/native_library_mac.mm index 742d92a..9f7a967 100644 --- a/base/native_library_mac.mm +++ b/base/native_library_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -16,7 +16,8 @@ namespace base { // static -NativeLibrary LoadNativeLibrary(const FilePath& library_path) { +NativeLibrary LoadNativeLibrary(const FilePath& library_path, + std::string* error) { // dlopen() etc. open the file off disk. if (library_path.Extension() == "dylib" || !file_util::DirectoryExists(library_path)) { diff --git a/base/native_library_win.cc b/base/native_library_win.cc index b77fbe1..af00cd1 100644 --- a/base/native_library_win.cc +++ b/base/native_library_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -39,7 +39,8 @@ NativeLibrary LoadNativeLibraryHelper(const FilePath& library_path, } // static -NativeLibrary LoadNativeLibrary(const FilePath& library_path) { +NativeLibrary LoadNativeLibrary(const FilePath& library_path, + std::string* error) { return LoadNativeLibraryHelper(library_path, LoadLibraryW); } diff --git a/base/nix/xdg_util.cc b/base/nix/xdg_util.cc index b39a07d..f824618 100644 --- a/base/nix/xdg_util.cc +++ b/base/nix/xdg_util.cc @@ -43,7 +43,8 @@ DesktopEnvironment GetDesktopEnvironment(Environment* env) { if (env->HasVar("KDE_SESSION_VERSION")) return DESKTOP_ENVIRONMENT_KDE4; return DESKTOP_ENVIRONMENT_KDE3; - } else if (desktop_session.find("xfce") != std::string::npos) { + } else if (desktop_session.find("xfce") != std::string::npos || + desktop_session == "xubuntu") { return DESKTOP_ENVIRONMENT_XFCE; } } diff --git a/base/nss_util.cc b/base/nss_util.cc deleted file mode 100644 index fe78fe0..0000000 --- a/base/nss_util.cc +++ /dev/null @@ -1,436 +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/nss_util.h" -#include "base/nss_util_internal.h" - -#include <nss.h> -#include <plarena.h> -#include <prerror.h> -#include <prinit.h> -#include <prtime.h> -#include <pk11pub.h> -#include <secmod.h> - -#if defined(OS_LINUX) -#include <linux/nfs_fs.h> -#include <sys/vfs.h> -#endif - -#include "base/file_util.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/stringprintf.h" -#include "base/threading/thread_restrictions.h" - -// USE_NSS means we use NSS for everything crypto-related. If USE_NSS is not -// defined, such as on Mac and Windows, we use NSS for SSL only -- we don't -// use NSS for crypto or certificate verification, and we don't use the NSS -// certificate and key databases. -#if defined(USE_NSS) -#include "base/crypto/crypto_module_blocking_password_delegate.h" -#include "base/environment.h" -#include "base/scoped_ptr.h" -#include "base/synchronization/lock.h" -#endif // defined(USE_NSS) - -namespace base { - -namespace { - -#if defined(USE_NSS) -FilePath GetDefaultConfigDirectory() { - FilePath dir = file_util::GetHomeDir(); - if (dir.empty()) { - LOG(ERROR) << "Failed to get home directory."; - return dir; - } - dir = dir.AppendASCII(".pki").AppendASCII("nssdb"); - if (!file_util::CreateDirectory(dir)) { - LOG(ERROR) << "Failed to create ~/.pki/nssdb directory."; - dir.clear(); - } - return dir; -} - -// On non-chromeos platforms, return the default config directory. -// On chromeos, return a read-only directory with fake root CA certs for testing -// (which will not exist on non-testing images). These root CA certs are used -// by the local Google Accounts server mock we use when testing our login code. -// If this directory is not present, NSS_Init() will fail. It is up to the -// caller to failover to NSS_NoDB_Init() at that point. -FilePath GetInitialConfigDirectory() { -#if defined(OS_CHROMEOS) - static const FilePath::CharType kReadOnlyCertDB[] = - FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb"); - return FilePath(kReadOnlyCertDB); -#else - return GetDefaultConfigDirectory(); -#endif // defined(OS_CHROMEOS) -} - -// This callback for NSS forwards all requests to a caller-specified -// CryptoModuleBlockingPasswordDelegate object. -char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) { - base::CryptoModuleBlockingPasswordDelegate* delegate = - reinterpret_cast<base::CryptoModuleBlockingPasswordDelegate*>(arg); - if (delegate) { - bool cancelled = false; - std::string password = delegate->RequestPassword(PK11_GetTokenName(slot), - retry != PR_FALSE, - &cancelled); - if (cancelled) - return NULL; - char* result = PORT_Strdup(password.c_str()); - password.replace(0, password.size(), password.size(), 0); - return result; - } - DLOG(ERROR) << "PK11 password requested with NULL arg"; - return NULL; -} - -// NSS creates a local cache of the sqlite database if it detects that the -// filesystem the database is on is much slower than the local disk. The -// detection doesn't work with the latest versions of sqlite, such as 3.6.22 -// (NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=578561). So we set -// the NSS environment variable NSS_SDB_USE_CACHE to "yes" to override NSS's -// detection when database_dir is on NFS. See http://crbug.com/48585. -// -// TODO(wtc): port this function to other USE_NSS platforms. It is defined -// only for OS_LINUX simply because the statfs structure is OS-specific. -// -// Because this function sets an environment variable it must be run before we -// go multi-threaded. -void UseLocalCacheOfNSSDatabaseIfNFS(const FilePath& database_dir) { -#if defined(OS_LINUX) - struct statfs buf; - if (statfs(database_dir.value().c_str(), &buf) == 0) { - if (buf.f_type == NFS_SUPER_MAGIC) { - scoped_ptr<Environment> env(Environment::Create()); - const char* use_cache_env_var = "NSS_SDB_USE_CACHE"; - if (!env->HasVar(use_cache_env_var)) - env->SetVar(use_cache_env_var, "yes"); - } - } -#endif // defined(OS_LINUX) -} - -// Load nss's built-in root certs. -SECMODModule *InitDefaultRootCerts() { - const char* kModulePath = "libnssckbi.so"; - char modparams[1024]; - snprintf(modparams, sizeof(modparams), - "name=\"Root Certs\" library=\"%s\"", kModulePath); - SECMODModule *root = SECMOD_LoadUserModule(modparams, NULL, PR_FALSE); - if (root) - return root; - - // Aw, snap. Can't find/load root cert shared library. - // This will make it hard to talk to anybody via https. - NOTREACHED(); - return NULL; -} -#endif // defined(USE_NSS) - -// A singleton to initialize/deinitialize NSPR. -// Separate from the NSS singleton because we initialize NSPR on the UI thread. -// Now that we're leaking the singleton, we could merge back with the NSS -// singleton. -class NSPRInitSingleton { - private: - friend struct DefaultLazyInstanceTraits<NSPRInitSingleton>; - - NSPRInitSingleton() { - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); - } - - // NOTE(willchan): We don't actually execute this code since we leak NSS to - // prevent non-joinable threads from using NSS after it's already been shut - // down. - ~NSPRInitSingleton() { - PL_ArenaFinish(); - PRStatus prstatus = PR_Cleanup(); - if (prstatus != PR_SUCCESS) { - LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?"; - } - } -}; - -LazyInstance<NSPRInitSingleton, LeakyLazyInstanceTraits<NSPRInitSingleton> > - g_nspr_singleton(LINKER_INITIALIZED); - -class NSSInitSingleton { - public: -#if defined(OS_CHROMEOS) - void OpenPersistentNSSDB() { - if (!chromeos_user_logged_in_) { - // GetDefaultConfigDirectory causes us to do blocking IO on UI thread. - // Temporarily allow it until we fix http://crbug.com.70119 - ThreadRestrictions::ScopedAllowIO allow_io; - chromeos_user_logged_in_ = true; - real_db_slot_ = OpenUserDB(GetDefaultConfigDirectory(), - "Real NSS database"); - } - } -#endif // defined(OS_CHROMEOS) - - bool OpenTestNSSDB(const FilePath& path, const char* description) { - test_db_slot_ = OpenUserDB(path, description); - return !!test_db_slot_; - } - - void CloseTestNSSDB() { - if (test_db_slot_) { - SECStatus status = SECMOD_CloseUserDB(test_db_slot_); - if (status != SECSuccess) - LOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); - PK11_FreeSlot(test_db_slot_); - test_db_slot_ = NULL; - } - } - - PK11SlotInfo* GetDefaultKeySlot() { - if (test_db_slot_) - return PK11_ReferenceSlot(test_db_slot_); - if (real_db_slot_) - return PK11_ReferenceSlot(real_db_slot_); - return PK11_GetInternalKeySlot(); - } - -#if defined(USE_NSS) - Lock* write_lock() { - return &write_lock_; - } -#endif // defined(USE_NSS) - - private: - friend struct DefaultLazyInstanceTraits<NSSInitSingleton>; - - NSSInitSingleton() - : real_db_slot_(NULL), - test_db_slot_(NULL), - root_(NULL), - chromeos_user_logged_in_(false) { - EnsureNSPRInit(); - - // We *must* have NSS >= 3.12.3. See bug 26448. - COMPILE_ASSERT( - (NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH >= 3) || - (NSS_VMAJOR == 3 && NSS_VMINOR > 12) || - (NSS_VMAJOR > 3), - nss_version_check_failed); - // Also check the run-time NSS version. - // NSS_VersionCheck is a >= check, not strict equality. - if (!NSS_VersionCheck("3.12.3")) { - // It turns out many people have misconfigured NSS setups, where - // their run-time NSPR doesn't match the one their NSS was compiled - // against. So rather than aborting, complain loudly. - LOG(ERROR) << "NSS_VersionCheck(\"3.12.3\") failed. " - "We depend on NSS >= 3.12.3, and this error is not fatal " - "only because many people have busted NSS setups (for " - "example, using the wrong version of NSPR). " - "Please upgrade to the latest NSS and NSPR, and if you " - "still get this error, contact your distribution " - "maintainer."; - } - - SECStatus status = SECFailure; -#if !defined(USE_NSS) - // Use the system certificate store, so initialize NSS without database. - status = NSS_NoDB_Init(NULL); - if (status != SECSuccess) { - LOG(ERROR) << "Error initializing NSS without a persistent " - "database: NSS error code " << PR_GetError(); - } -#else - FilePath database_dir = GetInitialConfigDirectory(); - if (!database_dir.empty()) { - // This duplicates the work which should have been done in - // EarlySetupForNSSInit. However, this function is idempotent so there's - // no harm done. - UseLocalCacheOfNSSDatabaseIfNFS(database_dir); - - // Initialize with a persistent database (likely, ~/.pki/nssdb). - // Use "sql:" which can be shared by multiple processes safely. - std::string nss_config_dir = - StringPrintf("sql:%s", database_dir.value().c_str()); -#if defined(OS_CHROMEOS) - status = NSS_Init(nss_config_dir.c_str()); -#else - status = NSS_InitReadWrite(nss_config_dir.c_str()); -#endif - if (status != SECSuccess) { - LOG(ERROR) << "Error initializing NSS with a persistent " - "database (" << nss_config_dir - << "): NSS error code " << PR_GetError(); - } - } - if (status != SECSuccess) { - LOG(WARNING) << "Initialize NSS without a persistent database " - "(~/.pki/nssdb)."; - status = NSS_NoDB_Init(NULL); - if (status != SECSuccess) { - LOG(ERROR) << "Error initializing NSS without a persistent " - "database: NSS error code " << PR_GetError(); - return; - } - } - - PK11_SetPasswordFunc(PKCS11PasswordFunc); - - // If we haven't initialized the password for the NSS databases, - // initialize an empty-string password so that we don't need to - // log in. - PK11SlotInfo* slot = PK11_GetInternalKeySlot(); - if (slot) { - // PK11_InitPin may write to the keyDB, but no other thread can use NSS - // yet, so we don't need to lock. - if (PK11_NeedUserInit(slot)) - PK11_InitPin(slot, NULL, NULL); - PK11_FreeSlot(slot); - } - - root_ = InitDefaultRootCerts(); -#endif // !defined(USE_NSS) - } - - // NOTE(willchan): We don't actually execute this code since we leak NSS to - // prevent non-joinable threads from using NSS after it's already been shut - // down. - ~NSSInitSingleton() { - if (real_db_slot_) { - SECMOD_CloseUserDB(real_db_slot_); - PK11_FreeSlot(real_db_slot_); - real_db_slot_ = NULL; - } - CloseTestNSSDB(); - if (root_) { - SECMOD_UnloadUserModule(root_); - SECMOD_DestroyModule(root_); - root_ = NULL; - } - - SECStatus status = NSS_Shutdown(); - if (status != SECSuccess) { - // We VLOG(1) because this failure is relatively harmless (leaking, but - // we're shutting down anyway). - VLOG(1) << "NSS_Shutdown failed; see " - "http://code.google.com/p/chromium/issues/detail?id=4609"; - } - } - - static PK11SlotInfo* OpenUserDB(const FilePath& path, - const char* description) { - const std::string modspec = - StringPrintf("configDir='sql:%s' tokenDescription='%s'", - path.value().c_str(), description); - PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); - if (db_slot) { - if (PK11_NeedUserInit(db_slot)) - PK11_InitPin(db_slot, NULL, NULL); - } - else { - LOG(ERROR) << "Error opening persistent database (" << modspec - << "): NSS error code " << PR_GetError(); - } - return db_slot; - } - - PK11SlotInfo* real_db_slot_; // Overrides internal key slot if non-NULL. - PK11SlotInfo* test_db_slot_; // Overrides internal key slot and real_db_slot_ - SECMODModule *root_; - bool chromeos_user_logged_in_; -#if defined(USE_NSS) - // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 - // is fixed, we will no longer need the lock. - Lock write_lock_; -#endif // defined(USE_NSS) -}; - -LazyInstance<NSSInitSingleton, LeakyLazyInstanceTraits<NSSInitSingleton> > - g_nss_singleton(LINKER_INITIALIZED); - -} // namespace - -#if defined(USE_NSS) -void EarlySetupForNSSInit() { - FilePath database_dir = GetInitialConfigDirectory(); - if (!database_dir.empty()) - UseLocalCacheOfNSSDatabaseIfNFS(database_dir); -} -#endif - -void EnsureNSPRInit() { - g_nspr_singleton.Get(); -} - -void EnsureNSSInit() { - // Initializing SSL causes us to do blocking IO. - // Temporarily allow it until we fix - // http://code.google.com/p/chromium/issues/detail?id=59847 - ThreadRestrictions::ScopedAllowIO allow_io; - 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); -} - -void CloseTestNSSDB() { - g_nss_singleton.Get().CloseTestNSSDB(); -} - -Lock* GetNSSWriteLock() { - return g_nss_singleton.Get().write_lock(); -} - -AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) { - // May be NULL if the lock is not needed in our version of NSS. - if (lock_) - lock_->Acquire(); -} - -AutoNSSWriteLock::~AutoNSSWriteLock() { - if (lock_) { - lock_->AssertAcquired(); - lock_->Release(); - } -} -#endif // defined(USE_NSS) - -#if defined(OS_CHROMEOS) -void OpenPersistentNSSDB() { - g_nss_singleton.Get().OpenPersistentNSSDB(); -} -#endif - -// TODO(port): Implement this more simply. We can convert by subtracting an -// offset (the difference between NSPR's and base::Time's epochs). -Time PRTimeToBaseTime(PRTime prtime) { - PRExplodedTime prxtime; - PR_ExplodeTime(prtime, PR_GMTParameters, &prxtime); - - Time::Exploded exploded; - exploded.year = prxtime.tm_year; - exploded.month = prxtime.tm_month + 1; - exploded.day_of_week = prxtime.tm_wday; - exploded.day_of_month = prxtime.tm_mday; - exploded.hour = prxtime.tm_hour; - exploded.minute = prxtime.tm_min; - exploded.second = prxtime.tm_sec; - exploded.millisecond = prxtime.tm_usec / 1000; - - return Time::FromUTCExploded(exploded); -} - -PK11SlotInfo* GetDefaultNSSKeySlot() { - return g_nss_singleton.Get().GetDefaultKeySlot(); -} - -} // namespace base diff --git a/base/nss_util.h b/base/nss_util.h deleted file mode 100644 index 10bbdfb..0000000 --- a/base/nss_util.h +++ /dev/null @@ -1,85 +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_NSS_UTIL_H_ -#define BASE_NSS_UTIL_H_ -#pragma once - -#include "base/basictypes.h" - -#if defined(USE_NSS) -class FilePath; -#endif // defined(USE_NSS) - -// This file specifically doesn't depend on any NSS or NSPR headers because it -// is included by various (non-crypto) parts of chrome to call the -// initialization functions. -namespace base { - -class Lock; -class Time; - -#if defined(USE_NSS) -// EarlySetupForNSSInit performs lightweight setup which must occur before the -// process goes multithreaded. This does not initialise NSS. For test, see -// EnsureNSSInit. -void EarlySetupForNSSInit(); -#endif - -// Initialize NRPR if it isn't already initialized. This function is -// thread-safe, and NSPR will only ever be initialized once. NSPR will be -// properly shut down on program exit. -void EnsureNSPRInit(); - -// Initialize NSS if it isn't already initialized. This must be called before -// any other NSS functions. This function is thread-safe, and NSS will only -// 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(); -#endif - -// Convert a NSS PRTime value into a base::Time object. -// We use a int64 instead of PRTime here to avoid depending on NSPR headers. -Time PRTimeToBaseTime(int64 prtime); - -#if defined(USE_NSS) -// Exposed for unittests only. |path| should be an existing directory under -// which the DB files will be placed. |description| is a user-visible name for -// the DB, as a utf8 string, which will be truncated at 32 bytes. -bool OpenTestNSSDB(const FilePath& path, const char* description); -void CloseTestNSSDB(); - -// NSS has a bug which can cause a deadlock or stall in some cases when writing -// to the certDB and keyDB. It also has a bug which causes concurrent key pair -// generations to scribble over each other. To work around this, we synchronize -// writes to the NSS databases with a global lock. The lock is hidden beneath a -// function for easy disabling when the bug is fixed. Callers should allow for -// it to return NULL in the future. -// -// See https://bugzilla.mozilla.org/show_bug.cgi?id=564011 -Lock* GetNSSWriteLock(); - -// A helper class that acquires the NSS write Lock while the AutoNSSWriteLock -// is in scope. -class AutoNSSWriteLock { - public: - AutoNSSWriteLock(); - ~AutoNSSWriteLock(); - private: - Lock *lock_; - DISALLOW_COPY_AND_ASSIGN(AutoNSSWriteLock); -}; - -#endif // defined(USE_NSS) - -} // namespace base - -#endif // BASE_NSS_UTIL_H_ diff --git a/base/nss_util_internal.h b/base/nss_util_internal.h deleted file mode 100644 index 139740b..0000000 --- a/base/nss_util_internal.h +++ /dev/null @@ -1,22 +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_NSS_SLOT_UTIL_H_ -#define BASE_NSS_SLOT_UTIL_H_ -#pragma once - -#include <secmodt.h> - -// These functions return a type defined in an NSS header, and so cannot be -// declared in nss_util.h. Hence, they are declared here. - -namespace base { - -// Returns a reference to the default NSS key slot. Caller must release -// reference with PK11_FreeSlot. -PK11SlotInfo* GetDefaultNSSKeySlot(); - -} // namespace base - -#endif // BASE_NSS_UTIL_H_ diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h index 47a662e..43c6913 100644 --- a/base/observer_list_threadsafe.h +++ b/base/observer_list_threadsafe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,9 +12,9 @@ #include "base/basictypes.h" #include "base/callback.h" #include "base/logging.h" +#include "base/memory/ref_counted.h" #include "base/message_loop.h" #include "base/observer_list.h" -#include "base/ref_counted.h" #include "base/task.h" /////////////////////////////////////////////////////////////////////////////// diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc index 652d358..d313367 100644 --- a/base/observer_list_unittest.cc +++ b/base/observer_list_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,8 +7,8 @@ #include <vector> +#include "base/memory/ref_counted.h" #include "base/message_loop.h" -#include "base/ref_counted.h" #include "base/threading/platform_thread.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/openssl_util.cc b/base/openssl_util.cc deleted file mode 100644 index 931485a..0000000 --- a/base/openssl_util.cc +++ /dev/null @@ -1,113 +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/openssl_util.h" - -#include <openssl/err.h> -#include <openssl/ssl.h> - -#include "base/logging.h" -#include "base/scoped_vector.h" -#include "base/singleton.h" -#include "base/string_piece.h" -#include "base/synchronization/lock.h" - -namespace base { - -namespace { - -unsigned long CurrentThreadId() { - return static_cast<unsigned long>(PlatformThread::CurrentId()); -} - -// Singleton for initializing and cleaning up the OpenSSL library. -class OpenSSLInitSingleton { - public: - 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 - // runner has completed. - // - There are other OpenSSL related singletons (e.g. the client socket - // context) who's cleanup depends on the global environment here, but - // we can't control the order the AtExit handlers will run in so - // allowing the global environment to leak at least ensures it is - // available for those other singletons to reliably cleanup. - return Singleton<OpenSSLInitSingleton, - LeakySingletonTraits<OpenSSLInitSingleton> >::get(); - } - private: - friend struct DefaultSingletonTraits<OpenSSLInitSingleton>; - OpenSSLInitSingleton() { - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - int num_locks = CRYPTO_num_locks(); - locks_.reserve(num_locks); - for (int i = 0; i < num_locks; ++i) - locks_.push_back(new base::Lock()); - CRYPTO_set_locking_callback(LockingCallback); - CRYPTO_set_id_callback(CurrentThreadId); - } - - ~OpenSSLInitSingleton() { - CRYPTO_set_locking_callback(NULL); - EVP_cleanup(); - ERR_free_strings(); - } - - static void LockingCallback(int mode, int n, const char* file, int line) { - OpenSSLInitSingleton::GetInstance()->OnLockingCallback(mode, n, file, line); - } - - void OnLockingCallback(int mode, int n, const char* file, int line) { - CHECK_LT(static_cast<size_t>(n), locks_.size()); - if (mode & CRYPTO_LOCK) - locks_[n]->Acquire(); - else - locks_[n]->Release(); - } - - // These locks are used and managed by OpenSSL via LockingCallback(). - ScopedVector<base::Lock> locks_; - - 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::GetInstance(); -} - -void ClearOpenSSLERRStack(const tracked_objects::Location& location) { - if (logging::DEBUG_MODE && VLOG_IS_ON(1)) { - 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; - ERR_print_errors_cb(&OpenSSLErrorCallback, NULL); - } else { - ERR_clear_error(); - } -} - -} // namespace base diff --git a/base/path_service.cc b/base/path_service.cc index 117feb5..e72ae7d 100644 --- a/base/path_service.cc +++ b/base/path_service.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -171,7 +171,7 @@ bool PathService::Get(int key, FilePath* result) { PathData* path_data = GetPathData(); DCHECK(path_data); DCHECK(result); - DCHECK(key >= base::DIR_CURRENT); + DCHECK_GE(key, base::DIR_CURRENT); // special case the current directory because it can never be cached if (key == base::DIR_CURRENT) @@ -208,7 +208,7 @@ bool PathService::Get(int key, FilePath* result) { bool PathService::Override(int key, const FilePath& path) { PathData* path_data = GetPathData(); DCHECK(path_data); - DCHECK(key > base::DIR_CURRENT) << "invalid path key"; + DCHECK_GT(key, base::DIR_CURRENT) << "invalid path key"; FilePath file_path = path; @@ -241,7 +241,7 @@ void PathService::RegisterProvider(ProviderFunc func, int key_start, int key_end) { PathData* path_data = GetPathData(); DCHECK(path_data); - DCHECK(key_end > key_start); + DCHECK_GT(key_end, key_start); base::AutoLock scoped_lock(path_data->lock); diff --git a/base/path_service.h b/base/path_service.h index edaa5e3..284fbf7 100644 --- a/base/path_service.h +++ b/base/path_service.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,18 +6,18 @@ #define BASE_PATH_SERVICE_H_ #pragma once -#include "build/build_config.h" - #include <string> +#include "base/base_api.h" #include "base/base_paths.h" +#include "build/build_config.h" class FilePath; // The path service is a global table mapping keys to file system paths. It is // OK to use this service from multiple threads. // -class PathService { +class BASE_API PathService { public: // Retrieves a path to a special directory or file and places it into the // string pointed to by 'path'. If you ask for a directory it is guaranteed diff --git a/base/pickle.cc b/base/pickle.cc index 116d3f1..afe35db 100644 --- a/base/pickle.cc +++ b/base/pickle.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -33,7 +33,7 @@ Pickle::Pickle(int header_size) header_size_(AlignInt(header_size, sizeof(uint32))), capacity_(0), variable_buffer_offset_(0) { - DCHECK(static_cast<size_t>(header_size) >= sizeof(Header)); + DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); DCHECK(header_size <= kPayloadUnit); Resize(kPayloadUnit); header_->payload_size = 0; diff --git a/base/pickle.h b/base/pickle.h index 9d449ae..20878e0 100644 --- a/base/pickle.h +++ b/base/pickle.h @@ -8,6 +8,7 @@ #include <string> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/logging.h" @@ -30,7 +31,7 @@ // space is controlled by the header_size parameter passed to the Pickle // constructor. // -class Pickle { +class BASE_API Pickle { public: // Initialize a Pickle object using the default header size. Pickle(); diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc index 51330c7..07be5e3 100644 --- a/base/pickle_unittest.cc +++ b/base/pickle_unittest.cc @@ -1,12 +1,12 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <string> #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "base/pickle.h" -#include "base/scoped_ptr.h" #include "base/string16.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/platform_file.h b/base/platform_file.h index dd3028b..461b060 100644 --- a/base/platform_file.h +++ b/base/platform_file.h @@ -6,16 +6,17 @@ #define BASE_PLATFORM_FILE_H_ #pragma once -#include "base/basictypes.h" #include "build/build_config.h" -#include "base/time.h" #if defined(OS_WIN) #include <windows.h> #endif #include <string> -class FilePath; +#include "base/base_api.h" +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/time.h" namespace base { @@ -41,7 +42,8 @@ enum PlatformFileFlags { PLATFORM_FILE_HIDDEN = 1024, // Used on Windows only PLATFORM_FILE_DELETE_ON_CLOSE = 2048, PLATFORM_FILE_TRUNCATE = 4096, - PLATFORM_FILE_WRITE_ATTRIBUTES = 8192 // Used on Windows only + PLATFORM_FILE_WRITE_ATTRIBUTES = 8192, // Used on Windows only + PLATFORM_FILE_ENUMERATE = 16384, // May enumerate directory }; // PLATFORM_FILE_ERROR_ACCESS_DENIED is returned when a call fails because of @@ -63,6 +65,7 @@ enum PlatformFileError { PLATFORM_FILE_ERROR_ABORT = -12, PLATFORM_FILE_ERROR_NOT_A_FILE = -13, PLATFORM_FILE_ERROR_NOT_EMPTY = -14, + PLATFORM_FILE_ERROR_INVALID_URL = -15, }; // Used to hold information about a given file. @@ -70,7 +73,7 @@ enum PlatformFileError { // make sure to update all functions that use it in file_util_{win|posix}.cc // too, and the ParamTraits<base::PlatformFileInfo> implementation in // chrome/common/common_param_traits.cc. -struct PlatformFileInfo { +struct BASE_API PlatformFileInfo { PlatformFileInfo(); ~PlatformFileInfo(); @@ -96,42 +99,39 @@ struct PlatformFileInfo { // Creates or opens the given file. If PLATFORM_FILE_OPEN_ALWAYS is used, and // |created| is provided, |created| will be set to true if the file was created // or to false in case the file was just opened. |error_code| can be NULL. -PlatformFile CreatePlatformFile(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error_code); -// Deprecated. -PlatformFile CreatePlatformFile(const std::wstring& name, - int flags, - bool* created); +BASE_API PlatformFile CreatePlatformFile(const FilePath& name, + int flags, + bool* created, + PlatformFileError* error_code); // Closes a file handle. Returns |true| on success and |false| otherwise. -bool ClosePlatformFile(PlatformFile file); +BASE_API bool ClosePlatformFile(PlatformFile file); // Reads the given number of bytes (or until EOF is reached) starting with the // given offset. Returns the number of bytes read, or -1 on error. -int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size); +BASE_API int ReadPlatformFile(PlatformFile file, int64 offset, + char* data, int size); // Writes the given buffer into the file at the given offset, overwritting any // data that was previously there. Returns the number of bytes written, or -1 // on error. -int WritePlatformFile(PlatformFile file, int64 offset, - const char* data, int size); +BASE_API int WritePlatformFile(PlatformFile file, int64 offset, + const char* data, int size); // Truncates the given file to the given length. If |length| is greater than // the current size of the file, the file is extended with zeros. If the file // doesn't exist, |false| is returned. -bool TruncatePlatformFile(PlatformFile file, int64 length); +BASE_API bool TruncatePlatformFile(PlatformFile file, int64 length); // Flushes the buffers of the given file. -bool FlushPlatformFile(PlatformFile file); +BASE_API bool FlushPlatformFile(PlatformFile file); // Touches the given file. -bool TouchPlatformFile(PlatformFile file, const Time& last_access_time, - const Time& last_modified_time); +BASE_API bool TouchPlatformFile(PlatformFile file, const Time& last_access_time, + const Time& last_modified_time); // Returns some information for the given file. -bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info); +BASE_API bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info); // Use this class to pass ownership of a PlatformFile to a receiver that may or // may not want to accept it. This class does not own the storage for the @@ -153,7 +153,7 @@ bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info); // ClosePlatformFile(file); // } // -class PassPlatformFile { +class BASE_API PassPlatformFile { public: explicit PassPlatformFile(PlatformFile* value) : value_(value) { } diff --git a/base/platform_file_posix.cc b/base/platform_file_posix.cc index 4e20e25..893997a 100644 --- a/base/platform_file_posix.cc +++ b/base/platform_file_posix.cc @@ -45,8 +45,7 @@ PlatformFile CreatePlatformFile(const FilePath& name, int flags, !(flags & PLATFORM_FILE_OPEN_ALWAYS)) { NOTREACHED(); errno = EOPNOTSUPP; - if (error_code) - *error_code = PLATFORM_FILE_ERROR_FAILED; + *error_code = error_code ? PLATFORM_FILE_ERROR_FAILED : PLATFORM_FILE_OK; return kInvalidPlatformFileValue; } @@ -67,7 +66,8 @@ PlatformFile CreatePlatformFile(const FilePath& name, int flags, COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero); - int descriptor = open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR); + int descriptor = + HANDLE_EINTR(open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR)); if (flags & PLATFORM_FILE_OPEN_ALWAYS) { if (descriptor > 0) { @@ -79,7 +79,8 @@ PlatformFile CreatePlatformFile(const FilePath& name, int flags, flags & PLATFORM_FILE_EXCLUSIVE_WRITE) { open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW } - descriptor = open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR); + descriptor = HANDLE_EINTR( + open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR)); if (created && descriptor > 0) *created = true; } @@ -134,14 +135,8 @@ PlatformFile CreatePlatformFile(const FilePath& name, int flags, return descriptor; } -PlatformFile CreatePlatformFile(const std::wstring& name, int flags, - bool* created) { - return CreatePlatformFile(FilePath::FromWStringHack(name), flags, - created, NULL); -} - bool ClosePlatformFile(PlatformFile file) { - return !close(file); + return !HANDLE_EINTR(close(file)); } int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { @@ -164,7 +159,7 @@ bool TruncatePlatformFile(PlatformFile file, int64 length) { } bool FlushPlatformFile(PlatformFile file) { - return !fsync(file); + return !HANDLE_EINTR(fsync(file)); } bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time, diff --git a/base/platform_file_unittest.cc b/base/platform_file_unittest.cc index e54ab61..dac2956 100644 --- a/base/platform_file_unittest.cc +++ b/base/platform_file_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/file_util.h" +#include "base/memory/scoped_temp_dir.h" #include "base/platform_file.h" -#include "base/scoped_temp_dir.h" #include "base/time.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/platform_file_win.cc b/base/platform_file_win.cc index f9eb234..0cb3e53 100644 --- a/base/platform_file_win.cc +++ b/base/platform_file_win.cc @@ -104,12 +104,6 @@ PlatformFile CreatePlatformFile(const FilePath& name, return file; } -PlatformFile CreatePlatformFile(const std::wstring& name, int flags, - bool* created) { - return CreatePlatformFile(FilePath::FromWStringHack(name), flags, - created, NULL); -} - bool ClosePlatformFile(PlatformFile file) { base::ThreadRestrictions::AssertIOAllowed(); return (CloseHandle(file) != 0); diff --git a/base/process.h b/base/process.h index 32f5131..9b1519a 100644 --- a/base/process.h +++ b/base/process.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #define BASE_PROCESS_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" #include "build/build_config.h" @@ -24,11 +25,13 @@ typedef HANDLE ProcessHandle; typedef DWORD ProcessId; typedef HANDLE UserTokenHandle; const ProcessHandle kNullProcessHandle = NULL; +const ProcessId kNullProcessId = 0; #elif defined(OS_POSIX) // On POSIX, our ProcessHandle will just be the PID. typedef pid_t ProcessHandle; typedef pid_t ProcessId; const ProcessHandle kNullProcessHandle = 0; +const ProcessId kNullProcessId = 0; #endif // defined(OS_WIN) #if defined(OS_POSIX) && !defined(OS_MACOSX) @@ -37,7 +40,7 @@ const ProcessHandle kNullProcessHandle = 0; const int kUnsetProcessPriority = 256; #endif -class Process { +class BASE_API Process { public: Process() : process_(kNullProcessHandle) { #if defined(OS_POSIX) && !defined(OS_MACOSX) diff --git a/base/process_linux.cc b/base/process_linux.cc index 14c2424..dfdc20e 100644 --- a/base/process_linux.cc +++ b/base/process_linux.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,7 +7,20 @@ #include <errno.h> #include <sys/resource.h> +#include "base/file_util.h" #include "base/logging.h" +#include "base/stringprintf.h" + +#if defined(OS_CHROMEOS) +static bool use_cgroups = false; +static bool cgroups_inited = false; +static const char kForegroundTasks[] = + "/tmp/cgroup/cpu/chrome_renderers/foreground/tasks"; +static const char kBackgroundTasks[] = + "/tmp/cgroup/cpu/chrome_renderers/background/tasks"; +static FilePath foreground_tasks; +static FilePath background_tasks; +#endif namespace base { @@ -28,6 +41,53 @@ bool Process::IsProcessBackgrounded() const { bool Process::SetProcessBackgrounded(bool background) { DCHECK(process_); +#if defined(OS_CHROMEOS) + // Check for cgroups files. ChromeOS supports these by default. It creates + // a cgroup mount in /tmp/cgroup and then configures two cpu task groups, + // one contains at most a single foreground renderer and the other contains + // all background renderers. This allows us to limit the impact of background + // renderers on foreground ones to a greater level than simple renicing. + if (!cgroups_inited) { + cgroups_inited = true; + foreground_tasks = FilePath(kForegroundTasks); + background_tasks = FilePath(kBackgroundTasks); + file_util::FileSystemType foreground_type; + file_util::FileSystemType background_type; + use_cgroups = + file_util::GetFileSystemType(foreground_tasks, &foreground_type) && + file_util::GetFileSystemType(background_tasks, &background_type) && + foreground_type == file_util::FILE_SYSTEM_CGROUP && + background_type == file_util::FILE_SYSTEM_CGROUP; + } + + if (use_cgroups) { + if (background) { + std::string pid = StringPrintf("%d", process_); + if (file_util::WriteFile(background_tasks, pid.c_str(), pid.size()) > 0) { + // With cgroups there's no real notion of priority as an int, but this + // will ensure we only move renderers back to the foreground group + // if we've ever put them in the background one. + saved_priority_ = 0; + return true; + } else { + return false; + } + } else { + if (saved_priority_ == kUnsetProcessPriority) { + // Can't restore if we were never backgrounded. + return false; + } + std::string pid = StringPrintf("%d", process_); + if (file_util::WriteFile(foreground_tasks, pid.c_str(), pid.size()) > 0) { + saved_priority_ = kUnsetProcessPriority; + return true; + } else { + return false; + } + } + } +#endif // OS_CHROMEOS + if (background) { // We won't be able to raise the priority if we don't have the right rlimit. // The limit may be adjusted in /etc/security/limits.conf for PAM systems. diff --git a/base/process_util.h b/base/process_util.h index 29b08ca..bdf9b9e 100644 --- a/base/process_util.h +++ b/base/process_util.h @@ -33,6 +33,7 @@ typedef struct _malloc_zone_t malloc_zone_t; #include <utility> #include <vector> +#include "base/base_api.h" #include "base/file_descriptor_shuffle.h" #include "base/file_path.h" #include "base/process.h" @@ -126,18 +127,19 @@ enum TerminationStatus { 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 + TERMINATION_STATUS_STILL_RUNNING, // child hasn't exited yet + TERMINATION_STATUS_MAX_ENUM }; // Returns the id of the current process. -ProcessId GetCurrentProcId(); +BASE_API ProcessId GetCurrentProcId(); // Returns the ProcessHandle of the current process. -ProcessHandle GetCurrentProcessHandle(); +BASE_API ProcessHandle GetCurrentProcessHandle(); // Converts a PID to a process handle. This handle must be closed by // CloseProcessHandle when you are done with it. Returns true on success. -bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle); +BASE_API bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle); // Converts a PID to a process handle. On Windows the handle is opened // with more access rights and must only be used by trusted code. @@ -145,21 +147,21 @@ bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle); // on success. // TODO(sanjeevr): Replace all calls to OpenPrivilegedProcessHandle with the // more specific OpenProcessHandleWithAccess method and delete this. -bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle); +BASE_API bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle); // Converts a PID to a process handle using the desired access flags. Use a // combination of the kProcessAccess* flags defined above for |access_flags|. -bool OpenProcessHandleWithAccess(ProcessId pid, - uint32 access_flags, - ProcessHandle* handle); +BASE_API bool OpenProcessHandleWithAccess(ProcessId pid, + uint32 access_flags, + ProcessHandle* handle); // Closes the process handle opened by OpenProcessHandle. -void CloseProcessHandle(ProcessHandle process); +BASE_API void CloseProcessHandle(ProcessHandle process); // Returns the unique ID for the specified process. This is functionally the // same as Windows' GetProcessId(), but works on versions of Windows before // Win XP SP1 as well. -ProcessId GetProcId(ProcessHandle process); +BASE_API ProcessId GetProcId(ProcessHandle process); #if defined(OS_LINUX) // Returns the path to the executable of the given process. @@ -199,7 +201,8 @@ enum IntegrityLevel { // Determine the integrity level of the specified process. Returns false // if the system does not support integrity levels (pre-Vista) or in the case // of an underlying system failure. -bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel *level); +BASE_API bool GetProcessIntegrityLevel(ProcessHandle process, + IntegrityLevel *level); // Runs the given application name with the given command line. Normally, the // first command line argument should be the path to the process, and don't @@ -215,15 +218,15 @@ bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel *level); // stored there on a successful launch. // NOTE: In this case, the caller is responsible for closing the handle so // that it doesn't leak! -bool LaunchApp(const std::wstring& cmdline, - bool wait, bool start_hidden, ProcessHandle* process_handle); +BASE_API bool LaunchApp(const std::wstring& cmdline, + bool wait, bool start_hidden, + ProcessHandle* process_handle); // Same as LaunchApp, except allows the new process to inherit handles of the // parent process. -bool LaunchAppWithHandleInheritance(const std::wstring& cmdline, - bool wait, - bool start_hidden, - ProcessHandle* process_handle); +BASE_API bool LaunchAppWithHandleInheritance(const std::wstring& cmdline, + bool wait, bool start_hidden, + ProcessHandle* process_handle); // Runs the given application name with the given command line as if the user // represented by |token| had launched it. The caveats about |cmdline| and @@ -235,15 +238,18 @@ bool LaunchAppWithHandleInheritance(const std::wstring& cmdline, // To avoid hard to diagnose problems, this function internally loads the // environment variables associated with the user and if this operation fails // the entire call fails as well. -bool LaunchAppAsUser(UserTokenHandle token, const std::wstring& cmdline, - bool start_hidden, ProcessHandle* process_handle); +BASE_API bool LaunchAppAsUser(UserTokenHandle token, + const std::wstring& cmdline, + bool start_hidden, + ProcessHandle* process_handle); // Has the same behavior as LaunchAppAsUser, but offers the boolean option to // use an empty string for the desktop name and a boolean for allowing the // child process to inherit handles from its parent. -bool LaunchAppAsUser(UserTokenHandle token, const std::wstring& cmdline, - bool start_hidden, ProcessHandle* process_handle, - bool empty_desktop_name, bool inherit_handles); +BASE_API bool LaunchAppAsUser(UserTokenHandle token, + const std::wstring& cmdline, + bool start_hidden, ProcessHandle* process_handle, + bool empty_desktop_name, bool inherit_handles); #elif defined(OS_POSIX) @@ -291,14 +297,14 @@ char** AlterEnvironment(const environment_vector& changes, // Executes the application specified by cl. This function delegates to one // of the above two platform-specific functions. -bool LaunchApp(const CommandLine& cl, - bool wait, bool start_hidden, ProcessHandle* process_handle); +BASE_API bool LaunchApp(const CommandLine& cl, bool wait, bool start_hidden, + ProcessHandle* process_handle); // Executes the application specified by |cl| and wait for it to exit. Stores // the output (stdout) in |output|. Redirects stderr to /dev/null. Returns true // on success (application launched and exited cleanly, with exit code // indicating success). -bool GetAppOutput(const CommandLine& cl, std::string* output); +BASE_API bool GetAppOutput(const CommandLine& cl, std::string* output); #if defined(OS_POSIX) // A restricted version of |GetAppOutput()| which (a) clears the environment, @@ -322,22 +328,22 @@ 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 FilePath::StringType& executable_name, - const ProcessFilter* filter); +BASE_API int GetProcessCount(const FilePath::StringType& executable_name, + const ProcessFilter* filter); // Attempts to kill all the processes on the current machine that were launched // from the given executable name, ending them with the given exit code. If // 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 FilePath::StringType& executable_name, int exit_code, - const ProcessFilter* filter); +BASE_API bool KillProcesses(const FilePath::StringType& executable_name, + int exit_code, const ProcessFilter* filter); // Attempts to kill the process identified by the given process // entry structure, giving it the specified exit code. If |wait| is true, wait // for the process to be actually terminated before returning. // Returns true if this is successful, false otherwise. -bool KillProcess(ProcessHandle process, int exit_code, bool wait); +BASE_API bool KillProcess(ProcessHandle process, int exit_code, bool wait); #if defined(OS_POSIX) // Attempts to kill the process group identified by |process_group_id|. Returns @@ -346,7 +352,7 @@ bool KillProcessGroup(ProcessHandle process_group_id); #endif #if defined(OS_WIN) -bool KillProcessById(ProcessId process_id, int exit_code, bool wait); +BASE_API bool KillProcessById(ProcessId process_id, int exit_code, bool wait); #endif // Get the termination status of the process by interpreting the @@ -357,38 +363,38 @@ bool KillProcessById(ProcessId process_id, int exit_code, bool wait); // 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); +BASE_API TerminationStatus GetTerminationStatus(ProcessHandle handle, + int* exit_code); // Waits for process to exit. On POSIX systems, if the process hasn't been // signaled then puts the exit code in |exit_code|; otherwise it's considered // a failure. On Windows |exit_code| is always filled. Returns true on success, // and closes |handle| in any case. -bool WaitForExitCode(ProcessHandle handle, int* exit_code); +BASE_API bool WaitForExitCode(ProcessHandle handle, int* exit_code); // Waits for process to exit. If it did exit within |timeout_milliseconds|, -// then puts the exit code in |exit_code|, closes |handle|, and returns true. +// then puts the exit code in |exit_code|, and returns true. // In POSIX systems, if the process has been signaled then |exit_code| is set // to -1. Returns false on failure (the caller is then responsible for closing // |handle|). -bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, - int64 timeout_milliseconds); +// The caller is always responsible for closing the |handle|. +BASE_API bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, + int64 timeout_milliseconds); // Wait for all the processes based on the named executable to exit. If filter // 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 FilePath::StringType& executable_name, - int64 wait_milliseconds, - const ProcessFilter* filter); +BASE_API bool WaitForProcessesToExit( + const FilePath::StringType& executable_name, + int64 wait_milliseconds, + const ProcessFilter* filter); // Wait for a single process to exit. Return true if it exited cleanly within // the given time limit. On Linux |handle| must be a child process, however // on Mac and Windows it can be any process. -bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds); - -// Returns true when |wait_milliseconds| have elapsed and the process -// is still running. -bool CrashAwareSleep(ProcessHandle handle, int64 wait_milliseconds); +BASE_API bool WaitForSingleProcess(ProcessHandle handle, + int64 wait_milliseconds); // Waits a certain amount of time (can be 0) for all the processes with a given // executable name to exit, then kills off any of them that are still around. @@ -396,16 +402,16 @@ 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 FilePath::StringType& executable_name, - int64 wait_milliseconds, - int exit_code, - const ProcessFilter* filter); +BASE_API bool CleanupProcesses(const FilePath::StringType& executable_name, + int64 wait_milliseconds, + int exit_code, + const ProcessFilter* filter); // This class provides a way to iterate through a list of processes on the // current machine with a specified filter. // To use, create an instance and then call NextProcessEntry() until it returns // false. -class ProcessIterator { +class BASE_API ProcessIterator { public: typedef std::list<ProcessEntry> ProcessEntries; @@ -455,7 +461,7 @@ class ProcessIterator { // on the current machine that were started from the given executable // name. To use, create an instance and then call NextProcessEntry() // until it returns false. -class NamedProcessIterator : public ProcessIterator { +class BASE_API NamedProcessIterator : public ProcessIterator { public: NamedProcessIterator(const FilePath::StringType& executable_name, const ProcessFilter* filter); @@ -520,13 +526,13 @@ struct FreeMBytes { }; // Convert a POSIX timeval to microseconds. -int64 TimeValToMicroseconds(const struct timeval& tv); +BASE_API int64 TimeValToMicroseconds(const struct timeval& tv); // Provides performance metrics for a specified process (CPU usage, memory and // IO counters). To use it, invoke CreateProcessMetrics() to get an instance // for a specific process, then access the information with the different get // methods. -class ProcessMetrics { +class BASE_API ProcessMetrics { public: ~ProcessMetrics(); @@ -627,7 +633,7 @@ class ProcessMetrics { // Returns the memory commited by the system in KBytes. // Returns 0 if it can't compute the commit charge. -size_t GetSystemCommitCharge(); +BASE_API size_t GetSystemCommitCharge(); // Enables low fragmentation heap (LFH) for every heaps of this process. This // won't have any effect on heaps created after this function call. It will not @@ -635,11 +641,11 @@ size_t GetSystemCommitCharge(); // better to call this function early in initialization and again before // entering the main loop. // Note: Returns true on Windows 2000 without doing anything. -bool EnableLowFragmentationHeap(); +BASE_API bool EnableLowFragmentationHeap(); // Enables 'terminate on heap corruption' flag. Helps protect against heap // overflow. Has no effect if the OS doesn't provide the necessary facility. -void EnableTerminationOnHeapCorruption(); +BASE_API void EnableTerminationOnHeapCorruption(); #if !defined(OS_WIN) // Turns on process termination if memory runs out. This is handled on Windows @@ -651,16 +657,14 @@ malloc_zone_t* GetPurgeableZone(); #endif #endif -#if defined(UNIT_TEST) // Enables stack dump to console output on exception and signals. // When enabled, the process will quit immediately. This is meant to be used in // unit_tests only! -bool EnableInProcessStackDumping(); -#endif // defined(UNIT_TEST) +BASE_API bool EnableInProcessStackDumping(); // If supported on the platform, and the user has sufficent rights, increase // the current process's scheduling priority to a high priority. -void RaiseProcessToHighPriority(); +BASE_API void RaiseProcessToHighPriority(); #if defined(OS_MACOSX) // Restore the default exception handler, setting it to Apple Crash Reporter diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm index 39eabac..e2df2ca 100644 --- a/base/process_util_mac.mm +++ b/base/process_util_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -622,7 +622,33 @@ void oom_killer_new() { // === Core Foundation CFAllocators === -typedef ChromeCFAllocator* ChromeCFAllocatorRef; +bool CanGetContextForCFAllocator(long darwin_version) { + // TODO(avi): remove at final release; http://crbug.com/74589 + if (darwin_version == 11) { + NSLog(@"Unsure about the internals of CFAllocator but going to patch them " + "anyway. Watch out for crashes inside of CFAllocatorAllocate."); + } + return darwin_version == 9 || + darwin_version == 10 || + darwin_version == 11; +} + +CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator, + long darwin_version) { + if (darwin_version == 9 || darwin_version == 10) { + ChromeCFAllocator9and10* our_allocator = + const_cast<ChromeCFAllocator9and10*>( + reinterpret_cast<const ChromeCFAllocator9and10*>(allocator)); + return &our_allocator->_context; + } else if (darwin_version == 11) { + ChromeCFAllocator11* our_allocator = + const_cast<ChromeCFAllocator11*>( + reinterpret_cast<const ChromeCFAllocator11*>(allocator)); + return &our_allocator->_context; + } else { + return NULL; + } +} CFAllocatorAllocateCallBack g_old_cfallocator_system_default; CFAllocatorAllocateCallBack g_old_cfallocator_malloc; @@ -833,29 +859,30 @@ void EnableTerminationOnOutOfMemory() { << "Old allocators unexpectedly non-null"; bool cf_allocator_internals_known = - darwin_version == 9 || darwin_version == 10; + CanGetContextForCFAllocator(darwin_version); if (cf_allocator_internals_known) { - ChromeCFAllocatorRef allocator = const_cast<ChromeCFAllocatorRef>( - reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorSystemDefault)); - g_old_cfallocator_system_default = allocator->_context.allocate; + CFAllocatorContext* context = + ContextForCFAllocator(kCFAllocatorSystemDefault, darwin_version); + CHECK(context) << "Failed to get context for kCFAllocatorSystemDefault."; + g_old_cfallocator_system_default = context->allocate; CHECK(g_old_cfallocator_system_default) << "Failed to get kCFAllocatorSystemDefault allocation function."; - allocator->_context.allocate = oom_killer_cfallocator_system_default; + context->allocate = oom_killer_cfallocator_system_default; - allocator = const_cast<ChromeCFAllocatorRef>( - reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorMalloc)); - g_old_cfallocator_malloc = allocator->_context.allocate; + context = ContextForCFAllocator(kCFAllocatorMalloc, darwin_version); + CHECK(context) << "Failed to get context for kCFAllocatorMalloc."; + g_old_cfallocator_malloc = context->allocate; CHECK(g_old_cfallocator_malloc) << "Failed to get kCFAllocatorMalloc allocation function."; - allocator->_context.allocate = oom_killer_cfallocator_malloc; + context->allocate = oom_killer_cfallocator_malloc; - allocator = const_cast<ChromeCFAllocatorRef>( - reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorMallocZone)); - g_old_cfallocator_malloc_zone = allocator->_context.allocate; + context = ContextForCFAllocator(kCFAllocatorMallocZone, darwin_version); + CHECK(context) << "Failed to get context for kCFAllocatorMallocZone."; + g_old_cfallocator_malloc_zone = context->allocate; CHECK(g_old_cfallocator_malloc_zone) << "Failed to get kCFAllocatorMallocZone allocation function."; - allocator->_context.allocate = oom_killer_cfallocator_malloc_zone; + context->allocate = oom_killer_cfallocator_malloc_zone; } else { NSLog(@"Internals of CFAllocator not known; out-of-memory failures via " "CFAllocator will not result in termination. http://crbug.com/45650"); diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc index ce56625..47f04a9 100644 --- a/base/process_util_posix.cc +++ b/base/process_util_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -21,9 +21,10 @@ #include "base/debug/stack_trace.h" #include "base/dir_reader_posix.h" #include "base/eintr_wrapper.h" +#include "base/file_util.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/process_util.h" -#include "base/scoped_ptr.h" #include "base/stringprintf.h" #include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" @@ -160,10 +161,17 @@ void StackDumpSignalHandler(int signal, siginfo_t* info, ucontext_t* context) { void ResetChildSignalHandlersToDefaults() { // The previous signal handlers are likely to be meaningless in the child's // context so we reset them to the defaults for now. http://crbug.com/44953 - // These signal handlers are setup in browser_main.cc:BrowserMain - signal(SIGTERM, SIG_DFL); + // These signal handlers are set up at least in browser_main.cc:BrowserMain + // and process_util_posix.cc:EnableInProcessStackDumping. signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); + signal(SIGILL, SIG_DFL); + signal(SIGABRT, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGSYS, SIG_DFL); + signal(SIGTERM, SIG_DFL); } } // anonymous namespace @@ -300,7 +308,7 @@ void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { if (getrlimit(RLIMIT_NOFILE, &nofile)) { // getrlimit failed. Take a best guess. max_fds = kSystemDefaultMaxFds; - DLOG(ERROR) << "getrlimit(RLIMIT_NOFILE) failed: " << errno; + RAW_LOG(ERROR, "getrlimit(RLIMIT_NOFILE) failed"); } else { max_fds = nofile.rlim_cur; } @@ -326,7 +334,7 @@ void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { // Since we're just trying to close anything we can find, // ignore any error return values of close(). - int unused ALLOW_UNUSED = HANDLE_EINTR(close(fd)); + ignore_result(HANDLE_EINTR(close(fd))); } return; } @@ -509,12 +517,34 @@ bool LaunchAppImpl( if (pid == 0) { // Child process + // DANGER: fork() rule: in the child, if you don't end up doing exec*(), + // you call _exit() instead of exit(). This is because _exit() does not + // call any previously-registered (in the parent) exit handlers, which + // might do things like block waiting for threads that don't even exist + // in the child. + + // If a child process uses the readline library, the process block forever. + // In BSD like OSes including OS X it is safe to assign /dev/null as stdin. + // See http://crbug.com/56596. + int null_fd = HANDLE_EINTR(open("/dev/null", O_RDONLY)); + if (null_fd < 0) { + RAW_LOG(ERROR, "Failed to open /dev/null"); + _exit(127); + } + + file_util::ScopedFD null_fd_closer(&null_fd); + int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO)); + if (new_fd != STDIN_FILENO) { + RAW_LOG(ERROR, "Failed to dup /dev/null for stdin"); + _exit(127); + } + if (start_new_process_group) { // Instead of inheriting the process group ID of the parent, the child // starts off a new process group with pgid equal to its process ID. if (setpgid(0, 0) < 0) { - PLOG(ERROR) << "setpgid"; - return false; + RAW_LOG(ERROR, "setpgid failed"); + _exit(127); } } #if defined(OS_MACOSX) @@ -543,12 +573,6 @@ bool LaunchAppImpl( environ = new_environ.get(); - // Obscure fork() rule: in the child, if you don't end up doing exec*(), - // you call _exit() instead of exit(). This is because _exit() does not - // call any previously-registered (in the parent) exit handlers, which - // might do things like block waiting for threads that don't even exist - // in the child. - // fd_shuffle1 is mutated by this call because it cannot malloc. if (!ShuffleFileDescriptors(&fd_shuffle1)) _exit(127); @@ -712,14 +736,15 @@ bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, return false; if (!waitpid_success) return false; - if (!WIFEXITED(status)) - return false; if (WIFSIGNALED(status)) { *exit_code = -1; return true; } - *exit_code = WEXITSTATUS(status); - return true; + if (WIFEXITED(status)) { + *exit_code = WEXITSTATUS(status); + return true; + } + return false; } #if defined(OS_MACOSX) @@ -809,19 +834,6 @@ bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) { } } -bool CrashAwareSleep(ProcessHandle handle, int64 wait_milliseconds) { - bool waitpid_success; - int status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success); - if (status != -1) { - DCHECK(waitpid_success); - return !(WIFEXITED(status) || WIFSIGNALED(status)); - } else { - // If waitpid returned with an error, then the process doesn't exist - // (which most probably means it didn't exist before our call). - return waitpid_success; - } -} - int64 TimeValToMicroseconds(const struct timeval& tv) { static const int kMicrosecondsPerSecond = 1000000; int64 ret = tv.tv_sec; // Avoid (int * int) integer overflow. diff --git a/base/process_util_unittest.cc b/base/process_util_unittest.cc index 31e1dec..7082408 100644 --- a/base/process_util_unittest.cc +++ b/base/process_util_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,9 +10,9 @@ #include "base/eintr_wrapper.h" #include "base/file_path.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/process_util.h" -#include "base/scoped_ptr.h" #include "base/test/multiprocess_test.h" #include "base/test/test_timeouts.h" #include "base/threading/platform_thread.h" diff --git a/base/process_util_win.cc b/base/process_util_win.cc index 71f0a1a..a49b78c 100644 --- a/base/process_util_win.cc +++ b/base/process_util_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -15,8 +15,9 @@ #include "base/command_line.h" #include "base/debug/stack_trace.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" -#include "base/scoped_ptr.h" +#include "base/sys_info.h" #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" @@ -464,8 +465,7 @@ TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { bool WaitForExitCode(ProcessHandle handle, int* exit_code) { bool success = WaitForExitCodeWithTimeout(handle, exit_code, INFINITE); - if (!success) - CloseProcessHandle(handle); + CloseProcessHandle(handle); return success; } @@ -477,10 +477,6 @@ bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, if (!::GetExitCodeProcess(handle, &temp_code)) return false; - // Only close the handle on success, to give the caller a chance to forcefully - // terminate the process if he wants to. - CloseProcessHandle(handle); - *exit_code = temp_code; return true; } @@ -544,11 +540,6 @@ bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) { return retval; } -bool CrashAwareSleep(ProcessHandle handle, int64 wait_milliseconds) { - bool retval = WaitForSingleObject(handle, wait_milliseconds) == WAIT_TIMEOUT; - return retval; -} - bool CleanupProcesses(const std::wstring& executable_name, int64 wait_milliseconds, int exit_code, @@ -564,12 +555,11 @@ bool CleanupProcesses(const std::wstring& executable_name, /////////////////////////////////////////////////////////////////////////////// // ProcesMetrics -ProcessMetrics::ProcessMetrics(ProcessHandle process) : process_(process), - last_time_(0), - last_system_time_(0) { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - processor_count_ = system_info.dwNumberOfProcessors; +ProcessMetrics::ProcessMetrics(ProcessHandle process) + : process_(process), + processor_count_(base::SysInfo::NumberOfProcessors()), + last_time_(0), + last_system_time_(0) { } // static diff --git a/base/process_win.cc b/base/process_win.cc index cdb9390..2873d91 100644 --- a/base/process_win.cc +++ b/base/process_win.cc @@ -1,11 +1,11 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/process.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/process_util.h" -#include "base/scoped_ptr.h" namespace base { diff --git a/base/rand_util.cc b/base/rand_util.cc index 0576c94..4a455f1 100644 --- a/base/rand_util.cc +++ b/base/rand_util.cc @@ -37,7 +37,7 @@ double RandDouble() { } uint64 RandGenerator(uint64 max) { - DCHECK(max > 0); + DCHECK_GT(max, 0ULL); return base::RandUint64() % max; } diff --git a/base/rand_util.h b/base/rand_util.h index 699fc7f..a4ea479 100644 --- a/base/rand_util.h +++ b/base/rand_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,25 +6,26 @@ #define BASE_RAND_UTIL_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" namespace base { // Returns a random number in range [0, kuint64max]. Thread-safe. -uint64 RandUint64(); +BASE_API uint64 RandUint64(); // Returns a random number between min and max (inclusive). Thread-safe. -int RandInt(int min, int max); +BASE_API int RandInt(int min, int max); // Returns a random number in range [0, max). Thread-safe. // // Note that this can be used as an adapter for std::random_shuffle(): // Given a pre-populated |std::vector<int> myvector|, shuffle it as // std::random_shuffle(myvector.begin(), myvector.end(), base::RandGenerator); -uint64 RandGenerator(uint64 max); +BASE_API uint64 RandGenerator(uint64 max); // Returns a random double in range [0, 1). Thread-safe. -double RandDouble(); +BASE_API double RandDouble(); } // namespace base diff --git a/base/resource_util.h b/base/resource_util.h index 8a37f95..c867abc 100644 --- a/base/resource_util.h +++ b/base/resource_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,7 @@ #include <windows.h> +#include "base/base_api.h" #include "base/basictypes.h" namespace base { @@ -18,8 +19,8 @@ namespace base { // Function for getting a data resource (BINDATA) from a dll. Some // resources are optional, especially in unit tests, so this returns false // but doesn't raise an error if the resource can't be loaded. -bool GetDataResourceFromModule(HMODULE module, int resource_id, - void** data, size_t* length); +bool BASE_API GetDataResourceFromModule(HMODULE module, int resource_id, + void** data, size_t* length); } // namespace base #endif // BASE_RESOURCE_UTIL_H__ diff --git a/base/scoped_comptr_win.h b/base/scoped_comptr_win.h deleted file mode 100644 index 7f15885..0000000 --- a/base/scoped_comptr_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_comptr.h" - -using base::win::ScopedComPtr; diff --git a/base/scoped_ptr.h b/base/scoped_ptr.h index 0a90150..f36da51 100644 --- a/base/scoped_ptr.h +++ b/base/scoped_ptr.h @@ -1,383 +1,13 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Scopers help you manage ownership of a pointer, helping you easily manage the -// a pointer within a scope, and automatically destroying the pointer at the -// end of a scope. There are two main classes you will use, which correspond -// to the operators new/delete and new[]/delete[]. -// -// Example usage (scoped_ptr): -// { -// scoped_ptr<Foo> foo(new Foo("wee")); -// } // foo goes out of scope, releasing the pointer with it. -// -// { -// scoped_ptr<Foo> foo; // No pointer managed. -// foo.reset(new Foo("wee")); // Now a pointer is managed. -// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. -// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. -// foo->Method(); // Foo::Method() called. -// foo.get()->Method(); // Foo::Method() called. -// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer -// // manages a pointer. -// foo.reset(new Foo("wee4")); // foo manages a pointer again. -// foo.reset(); // Foo("wee4") destroyed, foo no longer -// // manages a pointer. -// } // foo wasn't managing a pointer, so nothing was destroyed. -// -// Example usage (scoped_array): -// { -// scoped_array<Foo> foo(new Foo[100]); -// foo.get()->Method(); // Foo::Method on the 0th element. -// foo[10].Method(); // Foo::Method on the 10th element. -// } - #ifndef BASE_SCOPED_PTR_H_ #define BASE_SCOPED_PTR_H_ #pragma once -// This is an implementation designed to match the anticipated future TR2 -// implementation of the scoped_ptr class, and its closely-related brethren, -// scoped_array, scoped_ptr_malloc. - -#include <assert.h> -#include <stddef.h> -#include <stdlib.h> - -#include "base/compiler_specific.h" - -// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> -// automatically deletes the pointer it holds (if any). -// That is, scoped_ptr<T> owns the T object that it points to. -// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. -// Also like T*, scoped_ptr<T> is thread-compatible, and once you -// dereference it, you get the threadsafety guarantees of T. -// -// The size of a scoped_ptr is small: -// sizeof(scoped_ptr<C>) == sizeof(C*) -template <class C> -class scoped_ptr { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_ptr. - // The input parameter must be allocated with new. - explicit scoped_ptr(C* p = NULL) : ptr_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~scoped_ptr() { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != ptr_) { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - ptr_ = p; - } - } - - // Accessors to get the owned object. - // operator* and operator-> will assert() if there is no current object. - C& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - C* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - C* get() const { return ptr_; } - - // Comparison operators. - // These return whether two scoped_ptr refer to the same object, not just to - // two different but equal objects. - bool operator==(C* p) const { return ptr_ == p; } - bool operator!=(C* p) const { return ptr_ != p; } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - C* tmp = ptr_; - ptr_ = p2.ptr_; - p2.ptr_ = tmp; - } - - // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() WARN_UNUSED_RESULT { - C* retVal = ptr_; - ptr_ = NULL; - return retVal; - } - - private: - C* ptr_; - - // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't - // make sense, and if C2 == C, it still doesn't make sense because you should - // never have the same object owned by two different scoped_ptrs. - template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; - template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; - - // Disallow evil constructors - scoped_ptr(const scoped_ptr&); - void operator=(const scoped_ptr&); -}; - -// Free functions -template <class C> -void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { - p1.swap(p2); -} - -template <class C> -bool operator==(C* p1, const scoped_ptr<C>& p2) { - return p1 == p2.get(); -} - -template <class C> -bool operator!=(C* p1, const scoped_ptr<C>& p2) { - return p1 != p2.get(); -} - -// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate -// with new [] and the destructor deletes objects with delete []. -// -// As with scoped_ptr<C>, a scoped_array<C> either points to an object -// or is NULL. A scoped_array<C> owns the object that it points to. -// scoped_array<T> is thread-compatible, and once you index into it, -// the returned objects have only the threadsafety guarantees of T. -// -// Size: sizeof(scoped_array<C>) == sizeof(C*) -template <class C> -class scoped_array { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to intializing with NULL. - // There is no way to create an uninitialized scoped_array. - // The input parameter must be allocated with new []. - explicit scoped_array(C* p = NULL) : array_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~scoped_array() { - enum { type_must_be_complete = sizeof(C) }; - delete[] array_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != array_) { - enum { type_must_be_complete = sizeof(C) }; - delete[] array_; - array_ = p; - } - } - - // Get one element of the current object. - // Will assert() if there is no current object, or index i is negative. - C& operator[](ptrdiff_t i) const { - assert(i >= 0); - assert(array_ != NULL); - return array_[i]; - } - - // Get a pointer to the zeroth element of the current object. - // If there is no current object, return NULL. - C* get() const { - return array_; - } - - // Comparison operators. - // These return whether two scoped_array refer to the same object, not just to - // two different but equal objects. - bool operator==(C* p) const { return array_ == p; } - bool operator!=(C* p) const { return array_ != p; } - - // Swap two scoped arrays. - void swap(scoped_array& p2) { - C* tmp = array_; - array_ = p2.array_; - p2.array_ = tmp; - } - - // Release an array. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() WARN_UNUSED_RESULT { - C* retVal = array_; - array_ = NULL; - return retVal; - } - - private: - C* array_; - - // Forbid comparison of different scoped_array types. - template <class C2> bool operator==(scoped_array<C2> const& p2) const; - template <class C2> bool operator!=(scoped_array<C2> const& p2) const; - - // Disallow evil constructors - scoped_array(const scoped_array&); - void operator=(const scoped_array&); -}; - -// Free functions -template <class C> -void swap(scoped_array<C>& p1, scoped_array<C>& p2) { - p1.swap(p2); -} - -template <class C> -bool operator==(C* p1, const scoped_array<C>& p2) { - return p1 == p2.get(); -} - -template <class C> -bool operator!=(C* p1, const scoped_array<C>& p2) { - return p1 != p2.get(); -} - -// This class wraps the c library function free() in a class that can be -// passed as a template argument to scoped_ptr_malloc below. -class ScopedPtrMallocFree { - public: - inline void operator()(void* x) const { - free(x); - } -}; - -// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a -// second template argument, the functor used to free the object. - -template<class C, class FreeProc = ScopedPtrMallocFree> -class scoped_ptr_malloc { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_ptr. - // The input parameter must be allocated with an allocator that matches the - // Free functor. For the default Free functor, this is malloc, calloc, or - // realloc. - explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} - - // Destructor. If there is a C object, call the Free functor. - ~scoped_ptr_malloc() { - free_(ptr_); - } - - // Reset. Calls the Free functor on the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (ptr_ != p) { - free_(ptr_); - ptr_ = p; - } - } - - // Get the current object. - // operator* and operator-> will cause an assert() failure if there is - // no current object. - C& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - - C* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - - C* get() const { - return ptr_; - } - - // Comparison operators. - // These return whether a scoped_ptr_malloc and a plain pointer refer - // to the same object, not just to two different but equal objects. - // For compatibility with the boost-derived implementation, these - // take non-const arguments. - bool operator==(C* p) const { - return ptr_ == p; - } - - bool operator!=(C* p) const { - return ptr_ != p; - } - - // Swap two scoped pointers. - void swap(scoped_ptr_malloc & b) { - C* tmp = b.ptr_; - b.ptr_ = ptr_; - ptr_ = tmp; - } - - // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() WARN_UNUSED_RESULT { - C* tmp = ptr_; - ptr_ = NULL; - return tmp; - } - - private: - C* ptr_; - - // no reason to use these: each scoped_ptr_malloc should have its own object - template <class C2, class GP> - bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; - template <class C2, class GP> - bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; - - static FreeProc const free_; - - // Disallow evil constructors - scoped_ptr_malloc(const scoped_ptr_malloc&); - void operator=(const scoped_ptr_malloc&); -}; - -template<class C, class FP> -FP const scoped_ptr_malloc<C, FP>::free_ = FP(); - -template<class C, class FP> inline -void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { - a.swap(b); -} - -template<class C, class FP> inline -bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { - return p == b.get(); -} - -template<class C, class FP> inline -bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { - return p != b.get(); -} +// FIXME: Remove this header when third_party/cacheinvalidation is fixed to not +// rely on it. +#include "base/memory/scoped_ptr.h" #endif // BASE_SCOPED_PTR_H_ diff --git a/base/sha1.h b/base/sha1.h index dd43686..7625189 100644 --- a/base/sha1.h +++ b/base/sha1.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,8 @@ #include <string> +#include "base/base_api.h" + namespace base { // This function performs SHA-1 operations. @@ -18,7 +20,12 @@ enum { // Computes the SHA-1 hash of the input string |str| and returns the full // hash. -std::string SHA1HashString(const std::string& str); +BASE_API std::string SHA1HashString(const std::string& str); + +// Computes the SHA-1 hash of the |len| bytes in |data| and puts the hash +// in |hash|. |hash| must be SHA1_LENGTH bytes long. +BASE_API void SHA1HashBytes(const unsigned char* data, size_t len, + unsigned char* hash); } // namespace base diff --git a/base/sha1_portable.cc b/base/sha1_portable.cc index cc05a5c..529fc90 100644 --- a/base/sha1_portable.cc +++ b/base/sha1_portable.cc @@ -4,6 +4,8 @@ #include "base/sha1.h" +#include <string.h> + #include "base/basictypes.h" namespace base { @@ -195,12 +197,19 @@ void SecureHashAlgorithm::Process() { } std::string SHA1HashString(const std::string& str) { + char hash[SecureHashAlgorithm::kDigestSizeBytes]; + SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()), + str.length(), reinterpret_cast<unsigned char*>(hash)); + return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes); +} + +void SHA1HashBytes(const unsigned char* data, size_t len, + unsigned char* hash) { SecureHashAlgorithm sha; - sha.Update(str.c_str(), str.length()); + sha.Update(data, len); sha.Final(); - std::string out(reinterpret_cast<const char*>(sha.Digest()), - SecureHashAlgorithm::kDigestSizeBytes); - return out; + + memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes); } } // namespace base diff --git a/base/sha1_unittest.cc b/base/sha1_unittest.cc index e445e8f..406150b 100644 --- a/base/sha1_unittest.cc +++ b/base/sha1_unittest.cc @@ -54,3 +54,55 @@ TEST(SHA1Test, Test3) { for (size_t i = 0; i < base::SHA1_LENGTH; i++) EXPECT_EQ(expected[i], output[i] & 0xFF); } + +TEST(SHA1Test, Test1Bytes) { + // Example A.1 from FIPS 180-2: one-block message. + std::string input = "abc"; + unsigned char output[base::SHA1_LENGTH]; + + unsigned char expected[] = { 0xa9, 0x99, 0x3e, 0x36, + 0x47, 0x06, 0x81, 0x6a, + 0xba, 0x3e, 0x25, 0x71, + 0x78, 0x50, 0xc2, 0x6c, + 0x9c, 0xd0, 0xd8, 0x9d }; + + base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(input.c_str()), + input.length(), output); + for (size_t i = 0; i < base::SHA1_LENGTH; i++) + EXPECT_EQ(expected[i], output[i]); +} + +TEST(SHA1Test, Test2Bytes) { + // Example A.2 from FIPS 180-2: multi-block message. + std::string input = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + unsigned char output[base::SHA1_LENGTH]; + + unsigned char expected[] = { 0x84, 0x98, 0x3e, 0x44, + 0x1c, 0x3b, 0xd2, 0x6e, + 0xba, 0xae, 0x4a, 0xa1, + 0xf9, 0x51, 0x29, 0xe5, + 0xe5, 0x46, 0x70, 0xf1 }; + + base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(input.c_str()), + input.length(), output); + for (size_t i = 0; i < base::SHA1_LENGTH; i++) + EXPECT_EQ(expected[i], output[i]); +} + +TEST(SHA1Test, Test3Bytes) { + // Example A.3 from FIPS 180-2: long message. + std::string input(1000000, 'a'); + unsigned char output[base::SHA1_LENGTH]; + + unsigned char expected[] = { 0x34, 0xaa, 0x97, 0x3c, + 0xd4, 0xc4, 0xda, 0xa4, + 0xf6, 0x1e, 0xeb, 0x2b, + 0xdb, 0xad, 0x27, 0x31, + 0x65, 0x34, 0x01, 0x6f }; + + base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(input.c_str()), + input.length(), output); + for (size_t i = 0; i < base::SHA1_LENGTH; i++) + EXPECT_EQ(expected[i], output[i]); +} diff --git a/base/sha1_win.cc b/base/sha1_win.cc index 853c244..233749b 100644 --- a/base/sha1_win.cc +++ b/base/sha1_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,7 +7,9 @@ #include <windows.h> #include <wincrypt.h> -#include "base/crypto/scoped_capi_types.h" +// This file is not being compiled at the moment (see bug 47218). If we keep +// sha1 inside base, we cannot depend on src/crypto. +// #include "crypto/scoped_capi_types.h" #include "base/logging.h" namespace base { diff --git a/base/sha2.cc b/base/sha2.cc deleted file mode 100644 index c0fd0ab..0000000 --- a/base/sha2.cc +++ /dev/null @@ -1,29 +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 "base/sha2.h" - -#include "base/stl_util-inl.h" -#include "base/third_party/nss/blapi.h" -#include "base/third_party/nss/sha256.h" - -namespace base { - -void SHA256HashString(const std::string& str, void* output, size_t len) { - SHA256Context ctx; - - SHA256_Begin(&ctx); - SHA256_Update(&ctx, reinterpret_cast<const unsigned char*>(str.data()), - static_cast<unsigned int>(str.length())); - SHA256_End(&ctx, static_cast<unsigned char*>(output), NULL, - static_cast<unsigned int>(len)); -} - -std::string SHA256HashString(const std::string& str) { - std::string output(SHA256_LENGTH, 0); - SHA256HashString(str, string_as_array(&output), output.size()); - return output; -} - -} // namespace base diff --git a/base/sha2.h b/base/sha2.h deleted file mode 100644 index 19e41c3..0000000 --- a/base/sha2.h +++ /dev/null @@ -1,32 +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. - -#ifndef BASE_SHA2_H_ -#define BASE_SHA2_H_ -#pragma once - -#include <string> - -namespace base { - -// These functions perform SHA-256 operations. -// -// Functions for SHA-384 and SHA-512 can be added when the need arises. - -enum { - SHA256_LENGTH = 32 // length in bytes of a SHA-256 hash -}; - -// Computes the SHA-256 hash of the input string 'str' and stores the first -// 'len' bytes of the hash in the output buffer 'output'. If 'len' > 32, -// only 32 bytes (the full hash) are stored in the 'output' buffer. -void SHA256HashString(const std::string& str, void* output, size_t len); - -// Convenience version of the above that returns the result in a 32-byte -// string. -std::string SHA256HashString(const std::string& str); - -} // namespace base - -#endif // BASE_SHA2_H_ diff --git a/base/sha2_openssl.cc b/base/sha2_openssl.cc deleted file mode 100644 index afbce2f..0000000 --- a/base/sha2_openssl.cc +++ /dev/null @@ -1,30 +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/sha2.h" - -#include <openssl/ssl.h> - -#include "base/basictypes.h" -#include "base/openssl_util.h" -#include "base/stl_util-inl.h" - -namespace base { - -void SHA256HashString(const std::string& str, void* output, size_t len) { - COMPILE_ASSERT(SHA256_LENGTH == SHA256_DIGEST_LENGTH, - API_and_OpenSSL_SHA256_lengths_must_match); - ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result( - reinterpret_cast<unsigned char*>(output), len); - ::SHA256(reinterpret_cast<const unsigned char*>(str.data()), str.size(), - result.safe_buffer()); -} - -std::string SHA256HashString(const std::string& str) { - std::string output(SHA256_LENGTH, 0); - SHA256HashString(str, string_as_array(&output), output.size()); - return output; -} - -} // namespace base diff --git a/base/sha2_unittest.cc b/base/sha2_unittest.cc deleted file mode 100644 index b0321e8..0000000 --- a/base/sha2_unittest.cc +++ /dev/null @@ -1,97 +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 "base/sha2.h" - -#include "base/basictypes.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(Sha256Test, Test1) { - // Example B.1 from FIPS 180-2: one-block message. - std::string input1 = "abc"; - int expected1[] = { 0xba, 0x78, 0x16, 0xbf, - 0x8f, 0x01, 0xcf, 0xea, - 0x41, 0x41, 0x40, 0xde, - 0x5d, 0xae, 0x22, 0x23, - 0xb0, 0x03, 0x61, 0xa3, - 0x96, 0x17, 0x7a, 0x9c, - 0xb4, 0x10, 0xff, 0x61, - 0xf2, 0x00, 0x15, 0xad }; - - uint8 output1[base::SHA256_LENGTH]; - base::SHA256HashString(input1, output1, sizeof(output1)); - for (size_t i = 0; i < base::SHA256_LENGTH; i++) - EXPECT_EQ(expected1[i], static_cast<int>(output1[i])); - - uint8 output_truncated1[4]; // 4 bytes == 32 bits - base::SHA256HashString(input1, output_truncated1, sizeof(output_truncated1)); - for (size_t i = 0; i < sizeof(output_truncated1); i++) - EXPECT_EQ(expected1[i], static_cast<int>(output_truncated1[i])); -} - -TEST(Sha256Test, Test1_String) { - // Same as the above, but using the wrapper that returns a std::string. - // Example B.1 from FIPS 180-2: one-block message. - std::string input1 = "abc"; - int expected1[] = { 0xba, 0x78, 0x16, 0xbf, - 0x8f, 0x01, 0xcf, 0xea, - 0x41, 0x41, 0x40, 0xde, - 0x5d, 0xae, 0x22, 0x23, - 0xb0, 0x03, 0x61, 0xa3, - 0x96, 0x17, 0x7a, 0x9c, - 0xb4, 0x10, 0xff, 0x61, - 0xf2, 0x00, 0x15, 0xad }; - - std::string output1 = base::SHA256HashString(input1); - ASSERT_EQ(base::SHA256_LENGTH, output1.size()); - for (size_t i = 0; i < base::SHA256_LENGTH; i++) - EXPECT_EQ(expected1[i], static_cast<uint8>(output1[i])); -} - -TEST(Sha256Test, Test2) { - // Example B.2 from FIPS 180-2: multi-block message. - std::string input2 = - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - int expected2[] = { 0x24, 0x8d, 0x6a, 0x61, - 0xd2, 0x06, 0x38, 0xb8, - 0xe5, 0xc0, 0x26, 0x93, - 0x0c, 0x3e, 0x60, 0x39, - 0xa3, 0x3c, 0xe4, 0x59, - 0x64, 0xff, 0x21, 0x67, - 0xf6, 0xec, 0xed, 0xd4, - 0x19, 0xdb, 0x06, 0xc1 }; - - uint8 output2[base::SHA256_LENGTH]; - base::SHA256HashString(input2, output2, sizeof(output2)); - for (size_t i = 0; i < base::SHA256_LENGTH; i++) - EXPECT_EQ(expected2[i], static_cast<int>(output2[i])); - - uint8 output_truncated2[6]; - base::SHA256HashString(input2, output_truncated2, sizeof(output_truncated2)); - for (size_t i = 0; i < sizeof(output_truncated2); i++) - EXPECT_EQ(expected2[i], static_cast<int>(output_truncated2[i])); -} - -TEST(Sha256Test, Test3) { - // Example B.3 from FIPS 180-2: long message. - std::string input3(1000000, 'a'); // 'a' repeated a million times - int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c, - 0x99, 0x14, 0xfb, 0x92, - 0x81, 0xa1, 0xc7, 0xe2, - 0x84, 0xd7, 0x3e, 0x67, - 0xf1, 0x80, 0x9a, 0x48, - 0xa4, 0x97, 0x20, 0x0e, - 0x04, 0x6d, 0x39, 0xcc, - 0xc7, 0x11, 0x2c, 0xd0 }; - - uint8 output3[base::SHA256_LENGTH]; - base::SHA256HashString(input3, output3, sizeof(output3)); - for (size_t i = 0; i < base::SHA256_LENGTH; i++) - EXPECT_EQ(expected3[i], static_cast<int>(output3[i])); - - uint8 output_truncated3[12]; - base::SHA256HashString(input3, output_truncated3, sizeof(output_truncated3)); - for (size_t i = 0; i < sizeof(output_truncated3); i++) - EXPECT_EQ(expected3[i], static_cast<int>(output_truncated3[i])); -} diff --git a/base/shared_memory.h b/base/shared_memory.h index a088682..cf07da3 100644 --- a/base/shared_memory.h +++ b/base/shared_memory.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -15,6 +15,7 @@ #endif #include <string> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/process.h" @@ -39,7 +40,7 @@ typedef ino_t SharedMemoryId; // Platform abstraction for shared memory. Provides a C++ wrapper // around the OS primitive for a memory mapped file. -class SharedMemory { +class BASE_API SharedMemory { public: SharedMemory(); diff --git a/base/shared_memory_posix.cc b/base/shared_memory_posix.cc index bd2c6e5..682dc5c 100644 --- a/base/shared_memory_posix.cc +++ b/base/shared_memory_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -142,7 +142,7 @@ bool SharedMemory::CreateNamed(const std::string& name, return false; const uint32 current_size = stat.st_size; if (current_size != size) { - if (ftruncate(fileno(fp), size) != 0) + if (HANDLE_EINTR(ftruncate(fileno(fp), size)) != 0) return false; if (fseeko(fp, size, SEEK_SET) != 0) return false; @@ -296,8 +296,12 @@ bool SharedMemory::FilePathForMemoryName(const std::string& mem_name, } void SharedMemory::LockOrUnlockCommon(int function) { +<<<<<<< HEAD DCHECK(mapped_file_ >= 0); #if !defined(ANDROID) +======= + DCHECK_GE(mapped_file_, 0); +>>>>>>> chromium.org at r12.0.742.93 while (lockf(mapped_file_, function, 0) < 0) { if (errno == EINTR) { continue; @@ -320,7 +324,7 @@ bool SharedMemory::ShareToProcessCommon(ProcessHandle process, SharedMemoryHandle *new_handle, bool close_self) { const int new_fd = dup(mapped_file_); - DCHECK(new_fd >= 0); + DCHECK_GE(new_fd, 0); new_handle->fd = new_fd; new_handle->auto_close = true; diff --git a/base/shared_memory_unittest.cc b/base/shared_memory_unittest.cc index b515e79..edcbb50 100644 --- a/base/shared_memory_unittest.cc +++ b/base/shared_memory_unittest.cc @@ -1,11 +1,11 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/basictypes.h" #include "base/mac/scoped_nsautorelease_pool.h" +#include "base/memory/scoped_ptr.h" #include "base/shared_memory.h" -#include "base/scoped_ptr.h" #include "base/test/multiprocess_test.h" #include "base/threading/platform_thread.h" #include "base/time.h" diff --git a/base/stack_container_unittest.cc b/base/stack_container_unittest.cc index e1392c1..816ee07 100644 --- a/base/stack_container_unittest.cc +++ b/base/stack_container_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,8 +6,8 @@ #include <algorithm> +#include "base/memory/ref_counted.h" #include "testing/gtest/include/gtest/gtest.h" -#include "base/ref_counted.h" namespace { diff --git a/base/string_number_conversions.h b/base/string_number_conversions.h index c3d79b6..a4b6e3e 100644 --- a/base/string_number_conversions.h +++ b/base/string_number_conversions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/string16.h" @@ -27,21 +28,21 @@ namespace base { // Number -> string conversions ------------------------------------------------ -std::string IntToString(int value); -string16 IntToString16(int value); +BASE_API std::string IntToString(int value); +BASE_API string16 IntToString16(int value); -std::string UintToString(unsigned value); -string16 UintToString16(unsigned value); +BASE_API std::string UintToString(unsigned value); +BASE_API string16 UintToString16(unsigned value); -std::string Int64ToString(int64 value); -string16 Int64ToString16(int64 value); +BASE_API std::string Int64ToString(int64 value); +BASE_API string16 Int64ToString16(int64 value); -std::string Uint64ToString(uint64 value); -string16 Uint64ToString16(uint64 value); +BASE_API std::string Uint64ToString(uint64 value); +BASE_API string16 Uint64ToString16(uint64 value); // DoubleToString converts the double to a string format that ignores the // locale. If you want to use locale specific formatting, use ICU. -std::string DoubleToString(double value); +BASE_API std::string DoubleToString(double value); // String -> number conversions ------------------------------------------------ @@ -57,29 +58,30 @@ std::string DoubleToString(double value); // - No characters parseable as a number at the beginning of the string. // |*output| will be set to 0. // - Empty string. |*output| will be set to 0. -bool StringToInt(const std::string& input, int* output); -bool StringToInt(std::string::const_iterator begin, - std::string::const_iterator end, - int* output); -bool StringToInt(const char* begin, const char* end, int* output); - -bool StringToInt(const string16& input, int* output); -bool StringToInt(string16::const_iterator begin, - string16::const_iterator end, - int* output); -bool StringToInt(const char16* begin, const char16* end, int* output); - -bool StringToInt64(const std::string& input, int64* output); -bool StringToInt64(std::string::const_iterator begin, - std::string::const_iterator end, - int64* output); -bool StringToInt64(const char* begin, const char* end, int64* output); - -bool StringToInt64(const string16& input, int64* output); -bool StringToInt64(string16::const_iterator begin, - string16::const_iterator end, - int64* output); -bool StringToInt64(const char16* begin, const char16* end, int64* output); +BASE_API bool StringToInt(const std::string& input, int* output); +BASE_API bool StringToInt(std::string::const_iterator begin, + std::string::const_iterator end, + int* output); +BASE_API bool StringToInt(const char* begin, const char* end, int* output); + +BASE_API bool StringToInt(const string16& input, int* output); +BASE_API bool StringToInt(string16::const_iterator begin, + string16::const_iterator end, + int* output); +BASE_API bool StringToInt(const char16* begin, const char16* end, int* output); + +BASE_API bool StringToInt64(const std::string& input, int64* output); +BASE_API bool StringToInt64(std::string::const_iterator begin, + std::string::const_iterator end, + int64* output); +BASE_API bool StringToInt64(const char* begin, const char* end, int64* output); + +BASE_API bool StringToInt64(const string16& input, int64* output); +BASE_API bool StringToInt64(string16::const_iterator begin, + string16::const_iterator end, + int64* output); +BASE_API bool StringToInt64(const char16* begin, const char16* end, + int64* output); // For floating-point conversions, only conversions of input strings in decimal // form are defined to work. Behavior with strings representing floating-point @@ -87,7 +89,7 @@ bool StringToInt64(const char16* begin, const char16* end, int64* output); // NaN and inf) is undefined. Otherwise, these behave the same as the integral // variants. This expects the input string to NOT be specific to the locale. // If your input is locale specific, use ICU to read the number. -bool StringToDouble(const std::string& input, double* output); +BASE_API bool StringToDouble(const std::string& input, double* output); // Hex encoding ---------------------------------------------------------------- @@ -97,20 +99,21 @@ bool StringToDouble(const std::string& input, double* output); // you suspect that the data you want to format might be large, the absolute // max size for |size| should be is // std::numeric_limits<size_t>::max() / 2 -std::string HexEncode(const void* bytes, size_t size); +BASE_API std::string HexEncode(const void* bytes, size_t size); // Best effort conversion, see StringToInt above for restrictions. -bool HexStringToInt(const std::string& input, int* output); -bool HexStringToInt(std::string::const_iterator begin, - std::string::const_iterator end, - int* output); -bool HexStringToInt(const char* begin, const char* end, int* output); +BASE_API bool HexStringToInt(const std::string& input, int* output); +BASE_API bool HexStringToInt(std::string::const_iterator begin, + std::string::const_iterator end, + int* output); +BASE_API bool HexStringToInt(const char* begin, const char* end, int* output); // Similar to the previous functions, except that output is a vector of bytes. // |*output| will contain as many bytes as were successfully parsed prior to the // error. There is no overflow, but input.size() must be evenly divisible by 2. // Leading 0x or +/- are not allowed. -bool HexStringToBytes(const std::string& input, std::vector<uint8>* output); +BASE_API bool HexStringToBytes(const std::string& input, + std::vector<uint8>* output); } // namespace base diff --git a/base/string_piece.cc b/base/string_piece.cc index 3ccb4f0..bf6291c 100644 --- a/base/string_piece.cc +++ b/base/string_piece.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Copied from strings/stringpiece.cc with modifications @@ -12,11 +12,6 @@ namespace base { typedef StringPiece::size_type size_type; -std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { - o.write(piece.data(), static_cast<std::streamsize>(piece.size())); - return o; -} - bool operator==(const StringPiece& x, const StringPiece& y) { if (x.size() != y.size()) return false; diff --git a/base/string_piece.h b/base/string_piece.h index 64326e1..60380b1 100644 --- a/base/string_piece.h +++ b/base/string_piece.h @@ -21,11 +21,12 @@ #include <string> +#include "base/base_api.h" #include "base/basictypes.h" namespace base { -class StringPiece { +class BASE_API StringPiece { public: // standard STL container boilerplate typedef size_t size_type; @@ -163,7 +164,7 @@ class StringPiece { size_type length_; }; -bool operator==(const StringPiece& x, const StringPiece& y); +BASE_API bool operator==(const StringPiece& x, const StringPiece& y); inline bool operator!=(const StringPiece& x, const StringPiece& y) { return !(x == y); diff --git a/base/string_split.h b/base/string_split.h index 9a9030a..f2e8c86 100644 --- a/base/string_split.h +++ b/base/string_split.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/base_api.h" #include "base/string16.h" namespace base { @@ -22,52 +23,52 @@ namespace base { // Where wchar_t is char16 (i.e. Windows), |c| must be in BMP // (Basic Multilingual Plane). Elsewhere (Linux/Mac), wchar_t // should be a valid Unicode code point (32-bit). -void SplitString(const std::wstring& str, - wchar_t c, - std::vector<std::wstring>* r); +BASE_API void SplitString(const std::wstring& str, + wchar_t c, + std::vector<std::wstring>* r); // NOTE: |c| must be in BMP (Basic Multilingual Plane) -void SplitString(const string16& str, - char16 c, - std::vector<string16>* r); +BASE_API void SplitString(const string16& str, + char16 c, + std::vector<string16>* r); // |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which // the trailing byte of a multi-byte character can be in the ASCII range. // UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. // Note: |c| must be in the ASCII range. -void SplitString(const std::string& str, - char c, - std::vector<std::string>* r); +BASE_API void SplitString(const std::string& str, + char c, + std::vector<std::string>* r); -bool SplitStringIntoKeyValues( +BASE_API bool SplitStringIntoKeyValues( const std::string& line, char key_value_delimiter, std::string* key, std::vector<std::string>* values); -bool SplitStringIntoKeyValuePairs( +BASE_API bool SplitStringIntoKeyValuePairs( const std::string& line, char key_value_delimiter, char key_value_pair_delimiter, std::vector<std::pair<std::string, std::string> >* kv_pairs); // The same as SplitString, but use a substring delimiter instead of a char. -void SplitStringUsingSubstr(const string16& str, - const string16& s, - std::vector<string16>* r); -void SplitStringUsingSubstr(const std::string& str, - const std::string& s, - std::vector<std::string>* r); +BASE_API void SplitStringUsingSubstr(const string16& str, + const string16& s, + std::vector<string16>* r); +BASE_API void SplitStringUsingSubstr(const std::string& str, + const std::string& s, + std::vector<std::string>* r); // The same as SplitString, but don't trim white space. // NOTE: |c| must be in BMP (Basic Multilingual Plane) -void SplitStringDontTrim(const string16& str, - char16 c, - std::vector<string16>* r); +BASE_API void SplitStringDontTrim(const string16& str, + char16 c, + std::vector<string16>* r); // |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which // the trailing byte of a multi-byte character can be in the ASCII range. // UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. // Note: |c| must be in the ASCII range. -void SplitStringDontTrim(const std::string& str, - char c, - std::vector<std::string>* r); +BASE_API void SplitStringDontTrim(const std::string& str, + char c, + std::vector<std::string>* r); // WARNING: this uses whitespace as defined by the HTML5 spec. If you need // a function similar to this but want to trim all types of whitespace, then @@ -77,12 +78,12 @@ void SplitStringDontTrim(const std::string& str, // Splits the string along whitespace (where whitespace is the five space // characters defined by HTML 5). Each contiguous block of non-whitespace // characters is added to result. -void SplitStringAlongWhitespace(const std::wstring& str, - std::vector<std::wstring>* result); -void SplitStringAlongWhitespace(const string16& str, - std::vector<string16>* result); -void SplitStringAlongWhitespace(const std::string& str, - std::vector<std::string>* result); +BASE_API void SplitStringAlongWhitespace(const std::wstring& str, + std::vector<std::wstring>* result); +BASE_API void SplitStringAlongWhitespace(const string16& str, + std::vector<string16>* result); +BASE_API void SplitStringAlongWhitespace(const std::string& str, + std::vector<std::string>* result); } // namespace base diff --git a/base/string_util.cc b/base/string_util.cc index b2d9e6c..7198dec 100644 --- a/base/string_util.cc +++ b/base/string_util.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -22,7 +22,7 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "base/singleton.h" +#include "base/memory/singleton.h" #include "base/third_party/dmg_fp/dmg_fp.h" #include "base/utf_string_conversion_utils.h" #include "base/utf_string_conversions.h" diff --git a/base/string_util.h b/base/string_util.h index ed7adec..81d31d3 100644 --- a/base/string_util.h +++ b/base/string_util.h @@ -13,6 +13,7 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/string16.h" @@ -35,28 +36,30 @@ namespace base { // Compares the two strings s1 and s2 without regard to case using // the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if // s2 > s1 according to a lexicographic comparison. -int strcasecmp(const char* s1, const char* s2); +BASE_API int strcasecmp(const char* s1, const char* s2); // Compares up to count characters of s1 and s2 without regard to case using // the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if // s2 > s1 according to a lexicographic comparison. -int strncasecmp(const char* s1, const char* s2, size_t count); +BASE_API int strncasecmp(const char* s1, const char* s2, size_t count); // Same as strncmp but for char16 strings. -int strncmp16(const char16* s1, const char16* s2, size_t count); +BASE_API int strncmp16(const char16* s1, const char16* s2, size_t count); // Wrapper for vsnprintf that always null-terminates and always returns the // number of characters that would be in an untruncated formatted // string, even when truncation occurs. -int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) +BASE_API int vsnprintf(char* buffer, size_t size, const char* format, + va_list arguments) PRINTF_FORMAT(3, 0); // vswprintf always null-terminates, but when truncation occurs, it will either // return -1 or the number of characters that would be in an untruncated // formatted string. The actual return value depends on the underlying // C library's vswprintf implementation. -int vswprintf(wchar_t* buffer, size_t size, - const wchar_t* format, va_list arguments) WPRINTF_FORMAT(3, 0); +BASE_API int vswprintf(wchar_t* buffer, size_t size, + const wchar_t* format, va_list arguments) + WPRINTF_FORMAT(3, 0); // Some of these implementations need to be inlined. @@ -90,8 +93,8 @@ inline int swprintf(wchar_t* buffer, size_t size, const wchar_t* format, ...) { // long as |dst_size| is not 0. Returns the length of |src| in characters. // If the return value is >= dst_size, then the output was truncated. // NOTE: All sizes are in number of characters, NOT in bytes. -size_t strlcpy(char* dst, const char* src, size_t dst_size); -size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size); +BASE_API size_t strlcpy(char* dst, const char* src, size_t dst_size); +BASE_API size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size); // Scan a wprintf format string to determine whether it's portable across a // variety of systems. This function only checks that the conversion @@ -114,7 +117,7 @@ size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size); // working with wprintf. // // This function is intended to be called from base::vswprintf. -bool IsWprintfFormatPortable(const wchar_t* format); +BASE_API bool IsWprintfFormatPortable(const wchar_t* format); // ASCII-specific tolower. The standard library's tolower is locale sensitive, // so we don't want to use it here. @@ -165,9 +168,9 @@ template<typename Char> struct CaseInsensitiveCompareASCII { // have an empty string to use (e.g. in an error case). These should not be // used as initializers, function arguments, or return values for functions // which return by value or outparam. -const std::string& EmptyString(); -const std::wstring& EmptyWString(); -const string16& EmptyString16(); +BASE_API const std::string& EmptyString(); +BASE_API const std::wstring& EmptyWString(); +BASE_API const string16& EmptyString16(); extern const wchar_t kWhitespaceWide[]; extern const char16 kWhitespaceUTF16[]; @@ -178,33 +181,33 @@ extern const char kUtf8ByteOrderMark[]; // Removes characters in remove_chars from anywhere in input. Returns true if // any characters were removed. // NOTE: Safe to use the same variable for both input and output. -bool RemoveChars(const std::wstring& input, - const wchar_t remove_chars[], - std::wstring* output); -bool RemoveChars(const string16& input, - const char16 remove_chars[], - string16* output); -bool RemoveChars(const std::string& input, - const char remove_chars[], - std::string* output); +BASE_API bool RemoveChars(const std::wstring& input, + const wchar_t remove_chars[], + std::wstring* output); +BASE_API bool RemoveChars(const string16& input, + const char16 remove_chars[], + string16* output); +BASE_API bool RemoveChars(const std::string& input, + const char remove_chars[], + std::string* output); // Removes characters in trim_chars from the beginning and end of input. // NOTE: Safe to use the same variable for both input and output. -bool TrimString(const std::wstring& input, - const wchar_t trim_chars[], - std::wstring* output); -bool TrimString(const string16& input, - const char16 trim_chars[], - string16* output); -bool TrimString(const std::string& input, - const char trim_chars[], - std::string* output); +BASE_API bool TrimString(const std::wstring& input, + const wchar_t trim_chars[], + std::wstring* output); +BASE_API bool TrimString(const string16& input, + const char16 trim_chars[], + string16* output); +BASE_API bool TrimString(const std::string& input, + const char trim_chars[], + std::string* output); // Truncates a string to the nearest UTF-8 character that will leave // the string less than or equal to the specified byte size. -void TruncateUTF8ToByteSize(const std::string& input, - const size_t byte_size, - std::string* output); +BASE_API void TruncateUTF8ToByteSize(const std::string& input, + const size_t byte_size, + std::string* output); // Trims any whitespace from either end of the input string. Returns where // whitespace was found. @@ -219,21 +222,21 @@ enum TrimPositions { TRIM_TRAILING = 1 << 1, TRIM_ALL = TRIM_LEADING | TRIM_TRAILING, }; -TrimPositions TrimWhitespace(const std::wstring& input, - TrimPositions positions, - std::wstring* output); -TrimPositions TrimWhitespace(const string16& input, - TrimPositions positions, - string16* output); -TrimPositions TrimWhitespaceASCII(const std::string& input, - TrimPositions positions, - std::string* output); +BASE_API TrimPositions TrimWhitespace(const std::wstring& input, + TrimPositions positions, + std::wstring* output); +BASE_API TrimPositions TrimWhitespace(const string16& input, + TrimPositions positions, + string16* output); +BASE_API TrimPositions TrimWhitespaceASCII(const std::string& input, + TrimPositions positions, + std::string* output); // Deprecated. This function is only for backward compatibility and calls // TrimWhitespaceASCII(). -TrimPositions TrimWhitespace(const std::string& input, - TrimPositions positions, - std::string* output); +BASE_API TrimPositions TrimWhitespace(const std::string& input, + TrimPositions positions, + std::string* output); // Searches for CR or LF characters. Removes all contiguous whitespace // strings that contain them. This is useful when trying to deal with text @@ -243,33 +246,35 @@ TrimPositions TrimWhitespace(const std::string& input, // (2) If |trim_sequences_with_line_breaks| is true, any other whitespace // sequences containing a CR or LF are trimmed. // (3) All other whitespace sequences are converted to single spaces. -std::wstring CollapseWhitespace(const std::wstring& text, - bool trim_sequences_with_line_breaks); -string16 CollapseWhitespace(const string16& text, - bool trim_sequences_with_line_breaks); -std::string CollapseWhitespaceASCII(const std::string& text, - bool trim_sequences_with_line_breaks); +BASE_API std::wstring CollapseWhitespace(const std::wstring& text, + bool trim_sequences_with_line_breaks); +BASE_API string16 CollapseWhitespace(const string16& text, + bool trim_sequences_with_line_breaks); +BASE_API std::string CollapseWhitespaceASCII( + const std::string& text, bool trim_sequences_with_line_breaks); // Returns true if the passed string is empty or contains only white-space // characters. -bool ContainsOnlyWhitespaceASCII(const std::string& str); -bool ContainsOnlyWhitespace(const string16& str); +BASE_API bool ContainsOnlyWhitespaceASCII(const std::string& str); +BASE_API bool ContainsOnlyWhitespace(const string16& str); // Returns true if |input| is empty or contains only characters found in // |characters|. -bool ContainsOnlyChars(const std::wstring& input, - const std::wstring& characters); -bool ContainsOnlyChars(const string16& input, const string16& characters); -bool ContainsOnlyChars(const std::string& input, const std::string& characters); +BASE_API bool ContainsOnlyChars(const std::wstring& input, + const std::wstring& characters); +BASE_API bool ContainsOnlyChars(const string16& input, + const string16& characters); +BASE_API bool ContainsOnlyChars(const std::string& input, + const std::string& characters); // Converts to 7-bit ASCII by truncating. The result must be known to be ASCII // beforehand. -std::string WideToASCII(const std::wstring& wide); -std::string UTF16ToASCII(const string16& utf16); +BASE_API std::string WideToASCII(const std::wstring& wide); +BASE_API std::string UTF16ToASCII(const string16& utf16); // Converts the given wide string to the corresponding Latin1. This will fail // (return false) if any characters are more than 255. -bool WideToLatin1(const std::wstring& wide, std::string* latin1); +BASE_API bool WideToLatin1(const std::wstring& wide, std::string* latin1); // Returns true if the specified string matches the criteria. How can a wide // string be 8-bit or UTF8? It contains only characters that are < 256 (in the @@ -282,10 +287,10 @@ bool WideToLatin1(const std::wstring& wide, std::string* latin1); // to have the maximum 'discriminating' power from other encodings. If // there's a use case for just checking the structural validity, we have to // add a new function for that. -bool IsStringUTF8(const std::string& str); -bool IsStringASCII(const std::wstring& str); -bool IsStringASCII(const base::StringPiece& str); -bool IsStringASCII(const string16& str); +BASE_API bool IsStringUTF8(const std::string& str); +BASE_API bool IsStringASCII(const std::wstring& str); +BASE_API bool IsStringASCII(const base::StringPiece& str); +BASE_API bool IsStringASCII(const string16& str); // Converts the elements of the given string. This version uses a pointer to // clearly differentiate it from the non-pointer variant. @@ -319,55 +324,55 @@ template <class str> inline str StringToUpperASCII(const str& s) { // string. This is useful for doing checking if an input string matches some // token, and it is optimized to avoid intermediate string copies. This API is // borrowed from the equivalent APIs in Mozilla. -bool LowerCaseEqualsASCII(const std::string& a, const char* b); -bool LowerCaseEqualsASCII(const std::wstring& a, const char* b); -bool LowerCaseEqualsASCII(const string16& a, const char* b); +BASE_API bool LowerCaseEqualsASCII(const std::string& a, const char* b); +BASE_API bool LowerCaseEqualsASCII(const std::wstring& a, const char* b); +BASE_API bool LowerCaseEqualsASCII(const string16& a, const char* b); // Same thing, but with string iterators instead. -bool LowerCaseEqualsASCII(std::string::const_iterator a_begin, - std::string::const_iterator a_end, - const char* b); -bool LowerCaseEqualsASCII(std::wstring::const_iterator a_begin, - std::wstring::const_iterator a_end, - const char* b); -bool LowerCaseEqualsASCII(string16::const_iterator a_begin, - string16::const_iterator a_end, - const char* b); -bool LowerCaseEqualsASCII(const char* a_begin, - const char* a_end, - const char* b); -bool LowerCaseEqualsASCII(const wchar_t* a_begin, - const wchar_t* a_end, - const char* b); -bool LowerCaseEqualsASCII(const char16* a_begin, - const char16* a_end, - const char* b); +BASE_API bool LowerCaseEqualsASCII(std::string::const_iterator a_begin, + std::string::const_iterator a_end, + const char* b); +BASE_API bool LowerCaseEqualsASCII(std::wstring::const_iterator a_begin, + std::wstring::const_iterator a_end, + const char* b); +BASE_API bool LowerCaseEqualsASCII(string16::const_iterator a_begin, + string16::const_iterator a_end, + const char* b); +BASE_API bool LowerCaseEqualsASCII(const char* a_begin, + const char* a_end, + const char* b); +BASE_API bool LowerCaseEqualsASCII(const wchar_t* a_begin, + const wchar_t* a_end, + const char* b); +BASE_API bool LowerCaseEqualsASCII(const char16* a_begin, + const char16* a_end, + const char* b); // Performs a case-sensitive string compare. The behavior is undefined if both // strings are not ASCII. -bool EqualsASCII(const string16& a, const base::StringPiece& b); +BASE_API bool EqualsASCII(const string16& a, const base::StringPiece& b); // Returns true if str starts with search, or false otherwise. -bool StartsWithASCII(const std::string& str, - const std::string& search, - bool case_sensitive); -bool StartsWith(const std::wstring& str, - const std::wstring& search, - bool case_sensitive); -bool StartsWith(const string16& str, - const string16& search, - bool case_sensitive); +BASE_API bool StartsWithASCII(const std::string& str, + const std::string& search, + bool case_sensitive); +BASE_API bool StartsWith(const std::wstring& str, + const std::wstring& search, + bool case_sensitive); +BASE_API bool StartsWith(const string16& str, + const string16& search, + bool case_sensitive); // Returns true if str ends with search, or false otherwise. -bool EndsWith(const std::string& str, - const std::string& search, - bool case_sensitive); -bool EndsWith(const std::wstring& str, - const std::wstring& search, - bool case_sensitive); -bool EndsWith(const string16& str, - const string16& search, - bool case_sensitive); +BASE_API bool EndsWith(const std::string& str, + const std::string& search, + bool case_sensitive); +BASE_API bool EndsWith(const std::wstring& str, + const std::wstring& search, + bool case_sensitive); +BASE_API bool EndsWith(const string16& str, + const string16& search, + bool case_sensitive); // Determines the type of ASCII character, independent of locale (the C @@ -418,33 +423,34 @@ enum DataUnits { // Return the unit type that is appropriate for displaying the amount of bytes // passed in. -DataUnits GetByteDisplayUnits(int64 bytes); +BASE_API DataUnits GetByteDisplayUnits(int64 bytes); // Return a byte string in human-readable format, displayed in units appropriate // specified by 'units', with an optional unit suffix. // Ex: FormatBytes(512, DATA_UNITS_KIBIBYTE, true) => "0.5 KB" // Ex: FormatBytes(10*1024, DATA_UNITS_MEBIBYTE, false) => "0.1" -string16 FormatBytes(int64 bytes, DataUnits units, bool show_units); +BASE_API string16 FormatBytes(int64 bytes, DataUnits units, bool show_units); // As above, but with "/s" units. // Ex: FormatSpeed(512, DATA_UNITS_KIBIBYTE, true) => "0.5 KB/s" // Ex: FormatSpeed(10*1024, DATA_UNITS_MEBIBYTE, false) => "0.1" -string16 FormatSpeed(int64 bytes, DataUnits units, bool show_units); +BASE_API string16 FormatSpeed(int64 bytes, DataUnits units, bool show_units); // Return a number formated with separators in the user's locale way. // Ex: FormatNumber(1234567) => 1,234,567 -string16 FormatNumber(int64 number); +BASE_API string16 FormatNumber(int64 number); // Starting at |start_offset| (usually 0), replace the first instance of // |find_this| with |replace_with|. -void ReplaceFirstSubstringAfterOffset(string16* str, - string16::size_type start_offset, - const string16& find_this, - const string16& replace_with); -void ReplaceFirstSubstringAfterOffset(std::string* str, - std::string::size_type start_offset, - const std::string& find_this, - const std::string& replace_with); +BASE_API void ReplaceFirstSubstringAfterOffset(string16* str, + string16::size_type start_offset, + const string16& find_this, + const string16& replace_with); +BASE_API void ReplaceFirstSubstringAfterOffset( + std::string* str, + std::string::size_type start_offset, + const std::string& find_this, + const std::string& replace_with); // Starting at |start_offset| (usually 0), look through |str| and replace all // instances of |find_this| with |replace_with|. @@ -452,14 +458,14 @@ void ReplaceFirstSubstringAfterOffset(std::string* str, // This does entire substrings; use std::replace in <algorithm> for single // characters, for example: // std::replace(str.begin(), str.end(), 'a', 'b'); -void ReplaceSubstringsAfterOffset(string16* str, - string16::size_type start_offset, - const string16& find_this, - const string16& replace_with); -void ReplaceSubstringsAfterOffset(std::string* str, - std::string::size_type start_offset, - const std::string& find_this, - const std::string& replace_with); +BASE_API void ReplaceSubstringsAfterOffset(string16* str, + string16::size_type start_offset, + const string16& find_this, + const string16& replace_with); +BASE_API void ReplaceSubstringsAfterOffset(std::string* str, + std::string::size_type start_offset, + const std::string& find_this, + const std::string& replace_with); // This is mpcomplete's pattern for saving a string copy when dealing with // a function that writes results into a wchar_t[] and wanting the result to @@ -489,48 +495,49 @@ inline typename string_type::value_type* WriteInto(string_type* str, // Splits a string into its fields delimited by any of the characters in // |delimiters|. Each field is added to the |tokens| vector. Returns the // number of tokens found. -size_t Tokenize(const std::wstring& str, - const std::wstring& delimiters, - std::vector<std::wstring>* tokens); -size_t Tokenize(const string16& str, - const string16& delimiters, - std::vector<string16>* tokens); -size_t Tokenize(const std::string& str, - const std::string& delimiters, - std::vector<std::string>* tokens); -size_t Tokenize(const base::StringPiece& str, - const base::StringPiece& delimiters, - std::vector<base::StringPiece>* tokens); +BASE_API size_t Tokenize(const std::wstring& str, + const std::wstring& delimiters, + std::vector<std::wstring>* tokens); +BASE_API size_t Tokenize(const string16& str, + const string16& delimiters, + std::vector<string16>* tokens); +BASE_API size_t Tokenize(const std::string& str, + const std::string& delimiters, + std::vector<std::string>* tokens); +BASE_API size_t Tokenize(const base::StringPiece& str, + const base::StringPiece& delimiters, + std::vector<base::StringPiece>* tokens); // Does the opposite of SplitString(). -string16 JoinString(const std::vector<string16>& parts, char16 s); -std::string JoinString(const std::vector<std::string>& parts, char s); +BASE_API string16 JoinString(const std::vector<string16>& parts, char16 s); +BASE_API std::string JoinString(const std::vector<std::string>& parts, char s); // Replace $1-$2-$3..$9 in the format string with |a|-|b|-|c|..|i| respectively. // Additionally, any number of consecutive '$' characters is replaced by that // number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be // NULL. This only allows you to use up to nine replacements. -string16 ReplaceStringPlaceholders(const string16& format_string, - const std::vector<string16>& subst, - std::vector<size_t>* offsets); +BASE_API string16 ReplaceStringPlaceholders(const string16& format_string, + const std::vector<string16>& subst, + std::vector<size_t>* offsets); -std::string ReplaceStringPlaceholders(const base::StringPiece& format_string, - const std::vector<std::string>& subst, - std::vector<size_t>* offsets); +BASE_API std::string ReplaceStringPlaceholders( + const base::StringPiece& format_string, + const std::vector<std::string>& subst, + std::vector<size_t>* offsets); // Single-string shortcut for ReplaceStringHolders. |offset| may be NULL. -string16 ReplaceStringPlaceholders(const string16& format_string, - const string16& a, - size_t* offset); +BASE_API string16 ReplaceStringPlaceholders(const string16& format_string, + const string16& a, + size_t* offset); // 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 ? // We limit the patterns to having a max of 16 * or ? characters. // ? matches 0 or 1 character, while * matches 0 or more characters. -bool MatchPattern(const base::StringPiece& string, - const base::StringPiece& pattern); -bool MatchPattern(const string16& string, const string16& pattern); +BASE_API bool MatchPattern(const base::StringPiece& string, + const base::StringPiece& pattern); +BASE_API bool MatchPattern(const string16& string, const string16& pattern); // Hack to convert any char-like type to its unsigned counterpart. // For example, it will convert char, signed char and unsigned char to unsigned diff --git a/base/string_util_posix.h b/base/string_util_posix.h index 6053ada..d238f7f 100644 --- a/base/string_util_posix.h +++ b/base/string_util_posix.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -44,8 +44,15 @@ inline int strncmp16(const char16* s1, const char16* s2, size_t count) { inline int vswprintf(wchar_t* buffer, size_t size, const wchar_t* format, va_list arguments) { +#if defined(OS_OPENBSD) + // TODO(phajdan.jr): There is a patch to add vswprintf to OpenBSD, + // http://marc.info/?l=openbsd-tech&m=130003157729839&w=2 + NOTIMPLEMENTED(); + return -1; +#else DCHECK(IsWprintfFormatPortable(format)); return ::vswprintf(buffer, size, format, arguments); +#endif } } // namespace base diff --git a/base/stringprintf.h b/base/stringprintf.h index 9170ddd..fb32f20 100644 --- a/base/stringprintf.h +++ b/base/stringprintf.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,37 +9,42 @@ #include <string> +#include "base/base_api.h" #include "base/compiler_specific.h" namespace base { // Return a C++ string given printf-like input. -std::string StringPrintf(const char* format, ...) PRINTF_FORMAT(1, 2); -std::wstring StringPrintf(const wchar_t* format, ...) WPRINTF_FORMAT(1, 2); +BASE_API std::string StringPrintf(const char* format, ...) PRINTF_FORMAT(1, 2); +BASE_API std::wstring StringPrintf(const wchar_t* format, ...) + WPRINTF_FORMAT(1, 2); // Return a C++ string given vprintf-like input. -std::string StringPrintV(const char* format, va_list ap) PRINTF_FORMAT(1, 0); +BASE_API std::string StringPrintV(const char* format, va_list ap) + PRINTF_FORMAT(1, 0); // Store result into a supplied string and return it. -const std::string& SStringPrintf(std::string* dst, const char* format, ...) +BASE_API const std::string& SStringPrintf(std::string* dst, + const char* format, ...) PRINTF_FORMAT(2, 3); -const std::wstring& SStringPrintf(std::wstring* dst, - const wchar_t* format, ...) +BASE_API const std::wstring& SStringPrintf(std::wstring* dst, + const wchar_t* format, ...) WPRINTF_FORMAT(2, 3); // Append result to a supplied string. -void StringAppendF(std::string* dst, const char* format, ...) +BASE_API void StringAppendF(std::string* dst, const char* format, ...) PRINTF_FORMAT(2, 3); // TODO(evanm): this is only used in a few places in the code; // replace with string16 version. -void StringAppendF(std::wstring* dst, const wchar_t* format, ...) +BASE_API void StringAppendF(std::wstring* dst, const wchar_t* format, ...) WPRINTF_FORMAT(2, 3); // Lower-level routine that takes a va_list and appends to a specified // string. All other routines are just convenience wrappers around it. -void StringAppendV(std::string* dst, const char* format, va_list ap) +BASE_API void StringAppendV(std::string* dst, const char* format, va_list ap) PRINTF_FORMAT(2, 0); -void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) +BASE_API void StringAppendV(std::wstring* dst, + const wchar_t* format, va_list ap) WPRINTF_FORMAT(2, 0); } // namespace base diff --git a/base/sync_socket.h b/base/sync_socket.h index 1408b47..bcebbdf 100644 --- a/base/sync_socket.h +++ b/base/sync_socket.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -16,9 +16,11 @@ #endif #include <sys/types.h> +#include "base/base_api.h" + namespace base { -class SyncSocket { +class BASE_API SyncSocket { public: #if defined(OS_WIN) typedef HANDLE Handle; diff --git a/base/synchronization/cancellation_flag.h b/base/synchronization/cancellation_flag.h index 29ecd89..5738929 100644 --- a/base/synchronization/cancellation_flag.h +++ b/base/synchronization/cancellation_flag.h @@ -6,6 +6,7 @@ #define BASE_SYNCHRONIZATION_CANCELLATION_FLAG_H_ #pragma once +#include "base/base_api.h" #include "base/atomicops.h" #include "base/threading/platform_thread.h" @@ -16,7 +17,7 @@ namespace base { // is thread-safe. // // This class IS NOT intended for synchronization between threads. -class CancellationFlag { +class BASE_API CancellationFlag { public: CancellationFlag() : flag_(false) { #if !defined(NDEBUG) diff --git a/base/synchronization/condition_variable.h b/base/synchronization/condition_variable.h index db75a49..d70d4cd 100644 --- a/base/synchronization/condition_variable.h +++ b/base/synchronization/condition_variable.h @@ -74,6 +74,7 @@ #include <pthread.h> #endif +#include "base/base_api.h" #include "base/basictypes.h" #include "base/synchronization/lock.h" @@ -81,7 +82,7 @@ namespace base { class TimeDelta; -class ConditionVariable { +class BASE_API ConditionVariable { public: // Construct a cv for use with ONLY one user lock. explicit ConditionVariable(Lock* user_lock); diff --git a/base/synchronization/condition_variable_unittest.cc b/base/synchronization/condition_variable_unittest.cc index cf18320..808ecde 100644 --- a/base/synchronization/condition_variable_unittest.cc +++ b/base/synchronization/condition_variable_unittest.cc @@ -9,7 +9,7 @@ #include <vector> #include "base/logging.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/spin_wait.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" diff --git a/base/synchronization/lock.h b/base/synchronization/lock.h index f7c9c49..46d1ab3 100644 --- a/base/synchronization/lock.h +++ b/base/synchronization/lock.h @@ -6,6 +6,7 @@ #define BASE_SYNCHRONIZATION_LOCK_H_ #pragma once +#include "base/base_api.h" #include "base/synchronization/lock_impl.h" #include "base/threading/platform_thread.h" @@ -14,7 +15,7 @@ namespace base { // A convenient wrapper for an OS specific critical section. The only real // intelligence in this class is in debug mode for the support for the // AssertAcquired() method. -class Lock { +class BASE_API Lock { public: #if defined(NDEBUG) // Optimized wrapper implementation Lock() : lock_() {} diff --git a/base/synchronization/waitable_event.h b/base/synchronization/waitable_event.h index 9f357d1..1ab20fa 100644 --- a/base/synchronization/waitable_event.h +++ b/base/synchronization/waitable_event.h @@ -6,6 +6,7 @@ #define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" #if defined(OS_WIN) @@ -15,7 +16,7 @@ #if defined(OS_POSIX) #include <list> #include <utility> -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #endif @@ -41,7 +42,7 @@ class TimeDelta; // by a Windows event object. This is intentional. If you are writing Windows // specific code and you need other features of a Windows event, then you might // be better off just using an Windows event directly. -class WaitableEvent { +class BASE_API WaitableEvent { public: // If manual_reset is true, then to set the event state to non-signaled, a // consumer must call the Reset method. If this parameter is false, then the diff --git a/base/synchronization/waitable_event_watcher.h b/base/synchronization/waitable_event_watcher.h index 1b93b66..aa16d0b 100644 --- a/base/synchronization/waitable_event_watcher.h +++ b/base/synchronization/waitable_event_watcher.h @@ -15,6 +15,8 @@ #include "base/synchronization/waitable_event.h" #endif +#include "base/base_api.h" + namespace base { class Flag; @@ -58,7 +60,7 @@ class WaitableEvent; // it with a Watcher. It will act as if the event was never signaled. // ----------------------------------------------------------------------------- -class WaitableEventWatcher +class BASE_API WaitableEventWatcher #if defined(OS_POSIX) : public MessageLoop::DestructionObserver #endif diff --git a/base/sys_info.h b/base/sys_info.h index adfb250..863e068 100644 --- a/base/sys_info.h +++ b/base/sys_info.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #define BASE_SYS_INFO_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" #include <string> @@ -14,7 +15,7 @@ class FilePath; namespace base { -class SysInfo { +class BASE_API SysInfo { public: // Return the number of logical processors/cores on the current machine. static int NumberOfProcessors(); @@ -40,9 +41,9 @@ class SysInfo { // Retrieves detailed numeric values for the OS version. // TODO(port): Implement a Linux version of this method and enable the // corresponding unit test. - static void OperatingSystemVersionNumbers(int32 *major_version, - int32 *minor_version, - int32 *bugfix_version); + static void OperatingSystemVersionNumbers(int32* major_version, + int32* minor_version, + int32* bugfix_version); // Returns the CPU architecture of the system. Exact return value may differ // across platforms. @@ -72,9 +73,9 @@ class SysInfo { // Parses /etc/lsb-release to get version information for Google Chrome OS. // Declared here so it can be exposed for unit testing. static void ParseLsbRelease(const std::string& lsb_release, - int32 *major_version, - int32 *minor_version, - int32 *bugfix_version); + int32* major_version, + int32* minor_version, + int32* bugfix_version); #endif }; diff --git a/base/sys_info_chromeos.cc b/base/sys_info_chromeos.cc index 5834389..f724f99 100644 --- a/base/sys_info_chromeos.cc +++ b/base/sys_info_chromeos.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,69 +7,107 @@ #include "base/basictypes.h" #include "base/file_path.h" #include "base/file_util.h" +#include "base/lazy_instance.h" #include "base/string_number_conversions.h" #include "base/string_tokenizer.h" #include "base/threading/thread_restrictions.h" +#include <execinfo.h> + namespace base { -#if defined(GOOGLE_CHROME_BUILD) -static const char kLinuxStandardBaseVersionKey[] = "GOOGLE_RELEASE"; -#else -static const char kLinuxStandardBaseVersionKey[] = "DISTRIB_RELEASE"; -#endif +static const char* kLinuxStandardBaseVersionKeys[] = { + "CHROMEOS_RELEASE_VERSION", + "GOOGLE_RELEASE", + "DISTRIB_RELEASE", + NULL +}; const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release"; +struct ChromeOSVersionNumbers { + ChromeOSVersionNumbers() + : major_version(0), + minor_version(0), + bugfix_version(0), + parsed(false) { + } + + int32 major_version; + int32 minor_version; + int32 bugfix_version; + bool parsed; +}; + +static base::LazyInstance<ChromeOSVersionNumbers> + g_chrome_os_version_numbers(base::LINKER_INITIALIZED); + // static -void SysInfo::OperatingSystemVersionNumbers(int32 *major_version, - int32 *minor_version, - int32 *bugfix_version) { - // The other implementations of SysInfo don't block on the disk. - // See http://code.google.com/p/chromium/issues/detail?id=60394 - // Perhaps the caller ought to cache this? - // Temporary allowing while we work the bug out. - base::ThreadRestrictions::ScopedAllowIO allow_io; +void SysInfo::OperatingSystemVersionNumbers(int32* major_version, + int32* minor_version, + int32* bugfix_version) { + if (!g_chrome_os_version_numbers.Get().parsed) { + // The other implementations of SysInfo don't block on the disk. + // See http://code.google.com/p/chromium/issues/detail?id=60394 + // Perhaps the caller ought to cache this? + // Temporary allowing while we work the bug out. + base::ThreadRestrictions::ScopedAllowIO allow_io; - // TODO(cmasone): If this gets called a lot, it may kill performance. - // consider using static variables to cache these values? - FilePath path(kLinuxStandardBaseReleaseFile); - std::string contents; - if (file_util::ReadFileToString(path, &contents)) { - ParseLsbRelease(contents, major_version, minor_version, bugfix_version); + FilePath path(kLinuxStandardBaseReleaseFile); + std::string contents; + if (file_util::ReadFileToString(path, &contents)) { + g_chrome_os_version_numbers.Get().parsed = true; + ParseLsbRelease(contents, + &(g_chrome_os_version_numbers.Get().major_version), + &(g_chrome_os_version_numbers.Get().minor_version), + &(g_chrome_os_version_numbers.Get().bugfix_version)); + } } + *major_version = g_chrome_os_version_numbers.Get().major_version; + *minor_version = g_chrome_os_version_numbers.Get().minor_version; + *bugfix_version = g_chrome_os_version_numbers.Get().bugfix_version; } // static std::string SysInfo::GetLinuxStandardBaseVersionKey() { - return std::string(kLinuxStandardBaseVersionKey); + return std::string(kLinuxStandardBaseVersionKeys[0]); } // static void SysInfo::ParseLsbRelease(const std::string& lsb_release, - int32 *major_version, - int32 *minor_version, - int32 *bugfix_version) { - size_t version_key_index = lsb_release.find(kLinuxStandardBaseVersionKey); + int32* major_version, + int32* minor_version, + int32* bugfix_version) { + size_t version_key_index = std::string::npos; + for (int i = 0; kLinuxStandardBaseVersionKeys[i] != NULL; ++i) { + version_key_index = lsb_release.find(kLinuxStandardBaseVersionKeys[i]); + if (std::string::npos != version_key_index) { + break; + } + } if (std::string::npos == version_key_index) { return; } + size_t start_index = lsb_release.find_first_of('=', version_key_index); start_index++; // Move past '='. size_t length = lsb_release.find_first_of('\n', start_index) - start_index; std::string version = lsb_release.substr(start_index, length); StringTokenizer tokenizer(version, "."); - for (int i = 0; i < 3 && tokenizer.GetNext(); i++) { - if (0 == i) { + // TODO(rkc): Ignore the 0. here; fix this once we move Chrome OS version + // numbers from the 0.xx.yyy.zz format to the xx.yyy.zz format. + // Refer to http://code.google.com/p/chromium-os/issues/detail?id=15789 + for (int i = 0; i < 4 && tokenizer.GetNext(); i++) { + if (1 == i) { StringToInt(tokenizer.token_begin(), tokenizer.token_end(), major_version); *minor_version = *bugfix_version = 0; - } else if (1 == i) { + } else if (2 == i) { StringToInt(tokenizer.token_begin(), tokenizer.token_end(), minor_version); - } else { // 2 == i + } else { // 3 == i StringToInt(tokenizer.token_begin(), tokenizer.token_end(), bugfix_version); diff --git a/base/sys_info_mac.cc b/base/sys_info_mac.cc index 79caf55..e668421 100644 --- a/base/sys_info_mac.cc +++ b/base/sys_info_mac.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -14,9 +14,9 @@ namespace base { // static -void SysInfo::OperatingSystemVersionNumbers(int32 *major_version, - int32 *minor_version, - int32 *bugfix_version) { +void SysInfo::OperatingSystemVersionNumbers(int32* major_version, + int32* minor_version, + int32* bugfix_version) { Gestalt(gestaltSystemVersionMajor, reinterpret_cast<SInt32*>(major_version)); Gestalt(gestaltSystemVersionMinor, diff --git a/base/sys_info_unittest.cc b/base/sys_info_unittest.cc index 3e51890..da17684 100644 --- a/base/sys_info_unittest.cc +++ b/base/sys_info_unittest.cc @@ -67,9 +67,9 @@ TEST_F(SysInfoTest, GoogleChromeOSVersionNumbers) { &os_major_version, &os_minor_version, &os_bugfix_version); - EXPECT_EQ(1, os_major_version); - EXPECT_EQ(2, os_minor_version); - EXPECT_EQ(3, os_bugfix_version); + EXPECT_EQ(2, os_major_version); + EXPECT_EQ(3, os_minor_version); + EXPECT_EQ(4, os_bugfix_version); } TEST_F(SysInfoTest, GoogleChromeOSVersionNumbersFirst) { @@ -83,9 +83,9 @@ TEST_F(SysInfoTest, GoogleChromeOSVersionNumbersFirst) { &os_major_version, &os_minor_version, &os_bugfix_version); - EXPECT_EQ(1, os_major_version); - EXPECT_EQ(2, os_minor_version); - EXPECT_EQ(3, os_bugfix_version); + EXPECT_EQ(2, os_major_version); + EXPECT_EQ(3, os_minor_version); + EXPECT_EQ(4, os_bugfix_version); } TEST_F(SysInfoTest, GoogleChromeOSNoVersionNumbers) { diff --git a/base/sys_info_win.cc b/base/sys_info_win.cc index 83e099c..045d516 100644 --- a/base/sys_info_win.cc +++ b/base/sys_info_win.cc @@ -8,16 +8,15 @@ #include "base/file_path.h" #include "base/logging.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/stringprintf.h" +#include "base/win/windows_version.h" namespace base { // static int SysInfo::NumberOfProcessors() { - SYSTEM_INFO info; - GetSystemInfo(&info); - return static_cast<int>(info.dwNumberOfProcessors); + return win::OSInfo::GetInstance()->processors(); } // static @@ -54,12 +53,17 @@ std::string SysInfo::OperatingSystemName() { // static std::string SysInfo::OperatingSystemVersion() { - OSVERSIONINFO info = {0}; - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&info); - - return base::StringPrintf("%lu.%lu", - info.dwMajorVersion, info.dwMinorVersion); + win::OSInfo* os_info = win::OSInfo::GetInstance(); + win::OSInfo::VersionNumber version_number = os_info->version_number(); + std::string version(StringPrintf("%d.%d", version_number.major, + version_number.minor)); + win::OSInfo::ServicePack service_pack = os_info->service_pack(); + if (service_pack.major != 0) { + version += StringPrintf(" SP%d", service_pack.major); + if (service_pack.minor != 0) + version += StringPrintf(".%d", service_pack.minor); + } + return version; } // TODO: Implement OperatingSystemVersionComplete, which would include @@ -88,21 +92,16 @@ int SysInfo::DisplayCount() { // static size_t SysInfo::VMAllocationGranularity() { - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - - return sysinfo.dwAllocationGranularity; + return win::OSInfo::GetInstance()->allocation_granularity(); } // static -void SysInfo::OperatingSystemVersionNumbers(int32 *major_version, - int32 *minor_version, - int32 *bugfix_version) { - OSVERSIONINFO info = {0}; - info.dwOSVersionInfoSize = sizeof(info); - GetVersionEx(&info); - *major_version = info.dwMajorVersion; - *minor_version = info.dwMinorVersion; +void SysInfo::OperatingSystemVersionNumbers(int32* major_version, + int32* minor_version, + int32* bugfix_version) { + win::OSInfo* os_info = win::OSInfo::GetInstance(); + *major_version = os_info->version_number().major; + *minor_version = os_info->version_number().minor; *bugfix_version = 0; } diff --git a/base/sys_string_conversions.h b/base/sys_string_conversions.h index a96a687..4cf4b7a 100644 --- a/base/sys_string_conversions.h +++ b/base/sys_string_conversions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,8 @@ // but it is used in some shared code. Dependencies should be minimal. #include <string> + +#include "base/base_api.h" #include "base/basictypes.h" #include "base/string16.h" @@ -29,14 +31,14 @@ class StringPiece; // Converts between wide and UTF-8 representations of a string. On error, the // result is system-dependent. -std::string SysWideToUTF8(const std::wstring& wide); -std::wstring SysUTF8ToWide(const StringPiece& utf8); +BASE_API std::string SysWideToUTF8(const std::wstring& wide); +BASE_API std::wstring SysUTF8ToWide(const StringPiece& utf8); // Converts between wide and the system multi-byte representations of a string. // DANGER: This will lose information and can change (on Windows, this can // change between reboots). -std::string SysWideToNativeMB(const std::wstring& wide); -std::wstring SysNativeMBToWide(const StringPiece& native_mb); +BASE_API std::string SysWideToNativeMB(const std::wstring& wide); +BASE_API std::wstring SysNativeMBToWide(const StringPiece& native_mb); // Windows-specific ------------------------------------------------------------ @@ -45,8 +47,10 @@ std::wstring SysNativeMBToWide(const StringPiece& native_mb); // Converts between 8-bit and wide strings, using the given code page. The // code page identifier is one accepted by the Windows function // MultiByteToWideChar(). -std::wstring SysMultiByteToWide(const StringPiece& mb, uint32 code_page); -std::string SysWideToMultiByte(const std::wstring& wide, uint32 code_page); +BASE_API std::wstring SysMultiByteToWide(const StringPiece& mb, + uint32 code_page); +BASE_API std::string SysWideToMultiByte(const std::wstring& wide, + uint32 code_page); #endif // defined(OS_WIN) diff --git a/base/task.h b/base/task.h index 2deee56..8030169 100644 --- a/base/task.h +++ b/base/task.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,17 +6,18 @@ #define BASE_TASK_H_ #pragma once -#include "base/raw_scoped_refptr_mismatch_checker.h" +#include "base/base_api.h" +#include "base/memory/raw_scoped_refptr_mismatch_checker.h" +#include "base/memory/weak_ptr.h" #include "base/tracked.h" #include "base/tuple.h" -#include "base/weak_ptr.h" // Task ------------------------------------------------------------------------ // // A task is a generic runnable thingy, usually used for running code on a // different thread or for scheduling future tasks off of the message loop. -class Task : public tracked_objects::Tracked { +class BASE_API Task : public tracked_objects::Tracked { public: Task(); virtual ~Task(); @@ -25,7 +26,7 @@ class Task : public tracked_objects::Tracked { virtual void Run() = 0; }; -class CancelableTask : public Task { +class BASE_API CancelableTask : public Task { public: CancelableTask(); virtual ~CancelableTask(); diff --git a/base/task_queue.h b/base/task_queue.h index 75b38b2..8bd3cb7 100644 --- a/base/task_queue.h +++ b/base/task_queue.h @@ -8,12 +8,13 @@ #include <deque> +#include "base/base_api.h" #include "base/task.h" // A TaskQueue is a queue of tasks waiting to be run. To run the tasks, call // the Run method. A task queue is itself a Task so that it can be placed in a // message loop or another task queue. -class TaskQueue : public Task { +class BASE_API TaskQueue : public Task { public: TaskQueue(); ~TaskQueue(); diff --git a/base/task_queue_unittest.cc b/base/task_queue_unittest.cc index 90fc4cd..f2d2f49 100644 --- a/base/task_queue_unittest.cc +++ b/base/task_queue_unittest.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/basictypes.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/task.h" #include "base/task_queue.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/task_unittest.cc b/base/task_unittest.cc index cc975e0..25c201d 100644 --- a/base/task_unittest.cc +++ b/base/task_unittest.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/task.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/test/OWNERS b/base/test/OWNERS new file mode 100644 index 0000000..92ecc88 --- /dev/null +++ b/base/test/OWNERS @@ -0,0 +1 @@ +phajdan.jr@chromium.org diff --git a/base/test/test_file_util.h b/base/test/test_file_util.h index e59456a..9b9389d 100644 --- a/base/test/test_file_util.h +++ b/base/test/test_file_util.h @@ -47,6 +47,7 @@ bool HasInternetZoneIdentifier(const FilePath& full_path); // string16 elsewhere for Unicode strings, but in tests it is frequently // convenient to be able to compare paths to literals like L"foobar". std::wstring FilePathAsWString(const FilePath& path); +FilePath WStringAsFilePath(const std::wstring& path); } // namespace file_util diff --git a/base/test/test_file_util_posix.cc b/base/test/test_file_util_posix.cc index 430e52e..5adbcc2 100644 --- a/base/test/test_file_util_posix.cc +++ b/base/test/test_file_util_posix.cc @@ -113,5 +113,8 @@ bool EvictFileFromSystemCache(const FilePath& file) { std::wstring FilePathAsWString(const FilePath& path) { return UTF8ToWide(path.value()); } +FilePath WStringAsFilePath(const std::wstring& path) { + return FilePath(WideToUTF8(path)); +} } // namespace file_util diff --git a/base/test/test_file_util_win.cc b/base/test/test_file_util_win.cc index 1f20740..0159d2e 100644 --- a/base/test/test_file_util_win.cc +++ b/base/test/test_file_util_win.cc @@ -220,5 +220,8 @@ bool HasInternetZoneIdentifier(const FilePath& full_path) { std::wstring FilePathAsWString(const FilePath& path) { return path.value(); } +FilePath WStringAsFilePath(const std::wstring& path) { + return FilePath(path); +} } // namespace file_util diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc index 42b5b90..d952dc9 100644 --- a/base/test/test_suite.cc +++ b/base/test/test_suite.cc @@ -14,10 +14,9 @@ #include "base/i18n/icu_util.h" #include "base/logging.h" #include "base/mac/scoped_nsautorelease_pool.h" -#include "base/nss_util.h" +#include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/process_util.h" -#include "base/scoped_ptr.h" #include "base/test/multiprocess_test.h" #include "base/test/test_timeouts.h" #include "base/time.h" @@ -214,14 +213,6 @@ void TestSuite::Initialize() { icu_util::Initialize(); -#if defined(USE_NSS) - // Trying to repeatedly initialize and cleanup NSS and NSPR may result in - // a deadlock. Such repeated initialization will happen when using test - // isolation. Prevent problems by initializing NSS here, so that the cleanup - // will be done only on process exit. - base::EnsureNSSInit(); -#endif // defined(USE_NSS) - CatchMaybeTests(); TestTimeouts::Initialize(); diff --git a/base/test/test_switches.cc b/base/test/test_switches.cc index 991f4f3..d4491ee 100644 --- a/base/test/test_switches.cc +++ b/base/test/test_switches.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,6 +13,5 @@ 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"; const char switches::kUiTestTerminateTimeout[] = "ui-test-terminate-timeout"; const char switches::kUiTestTimeout[] = "test-timeout"; diff --git a/base/test/test_switches.h b/base/test/test_switches.h index 44ebd23..81891cb 100644 --- a/base/test/test_switches.h +++ b/base/test/test_switches.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -14,7 +14,6 @@ extern const char kTestLargeTimeout[]; extern const char kTestTinyTimeout[]; extern const char kUiTestActionTimeout[]; extern const char kUiTestActionMaxTimeout[]; -extern const char kUiTestCommandExecutionTimeout[]; extern const char kUiTestTerminateTimeout[]; extern const char kUiTestTimeout[]; diff --git a/base/test/test_timeouts.cc b/base/test/test_timeouts.cc index 20cd8a9..1d86b2c 100644 --- a/base/test/test_timeouts.cc +++ b/base/test/test_timeouts.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -44,14 +44,11 @@ bool TestTimeouts::initialized_ = false; // static int TestTimeouts::tiny_timeout_ms_ = 100; int TestTimeouts::action_timeout_ms_ = 2000; -int TestTimeouts::action_max_timeout_ms_ = 20000; +int TestTimeouts::action_max_timeout_ms_ = 25000; int TestTimeouts::large_test_timeout_ms_ = 3 * 60 * 1000; int TestTimeouts::huge_test_timeout_ms_ = 10 * 60 * 1000; // static -int TestTimeouts::command_execution_timeout_ms_ = 25000; - -// static int TestTimeouts::wait_for_terminate_timeout_ms_ = 15000; // static @@ -83,8 +80,6 @@ void TestTimeouts::Initialize() { CHECK(action_max_timeout_ms_ <= large_test_timeout_ms_); CHECK(large_test_timeout_ms_ <= huge_test_timeout_ms_); - InitializeTimeout(switches::kUiTestCommandExecutionTimeout, - &command_execution_timeout_ms_); InitializeTimeout(switches::kUiTestTerminateTimeout, &wait_for_terminate_timeout_ms_); diff --git a/base/test/test_timeouts.h b/base/test/test_timeouts.h index f4cb1ff..64df11a 100644 --- a/base/test/test_timeouts.h +++ b/base/test/test_timeouts.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -35,12 +35,6 @@ class TestTimeouts { // Do not use multiple times in a single test. static int huge_test_timeout_ms() { return huge_test_timeout_ms_; } - // Timeout to use for AutomationProxy. Do not use in other places. - // TODO(phajdan.jr): Remove command_execution_timeout_ms. - static int command_execution_timeout_ms() { - return command_execution_timeout_ms_; - } - // Timeout to wait for a process to terminate. static int wait_for_terminate_timeout_ms() { return wait_for_terminate_timeout_ms_; @@ -60,7 +54,6 @@ class TestTimeouts { static int action_max_timeout_ms_; static int large_test_timeout_ms_; static int huge_test_timeout_ms_; - static int command_execution_timeout_ms_; static int wait_for_terminate_timeout_ms_; static int live_operation_timeout_ms_; diff --git a/base/third_party/nspr/prcpucfg.h b/base/third_party/nspr/prcpucfg.h index 59e2cdf..b5f0497 100644 --- a/base/third_party/nspr/prcpucfg.h +++ b/base/third_party/nspr/prcpucfg.h @@ -34,7 +34,13 @@ #include "base/third_party/nspr/prcpucfg_win.h" #elif defined(__APPLE__) #include "base/third_party/nspr/prcpucfg_mac.h" +<<<<<<< HEAD #elif defined(__linux__) || defined(__native_client__) || defined(ANDROID) +======= +#elif defined(__native_client__) +#include "base/third_party/nspr/prcpucfg_nacl.h" +#elif defined(__linux__) +>>>>>>> chromium.org at r12.0.742.93 #include "base/third_party/nspr/prcpucfg_linux.h" #elif defined(__FreeBSD__) #include "base/third_party/nspr/prcpucfg_freebsd.h" diff --git a/base/third_party/nspr/prcpucfg_mac.h b/base/third_party/nspr/prcpucfg_mac.h index dc7e0e0..60bea8e 100644 --- a/base/third_party/nspr/prcpucfg_mac.h +++ b/base/third_party/nspr/prcpucfg_mac.h @@ -44,7 +44,7 @@ #define PR_AF_INET6 30 /* same as AF_INET6 */ -#if defined(i386) +#ifdef __LITTLE_ENDIAN__ #undef IS_BIG_ENDIAN #define IS_LITTLE_ENDIAN 1 #else @@ -52,10 +52,60 @@ #define IS_BIG_ENDIAN 1 #endif +#ifdef __x86_64__ +#define IS_64 +#endif + +#ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG +#endif #undef HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS 1 +#ifdef IS_64 + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 8 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_DOUBLE 8 +#define PR_BYTES_PER_WORD 8 +#define PR_BYTES_PER_DWORD 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 64 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_DOUBLE 64 +#define PR_BITS_PER_WORD 64 +#define PR_BITS_PER_DWORD 64 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 6 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_DOUBLE_LOG2 6 +#define PR_BITS_PER_WORD_LOG2 6 +#define PR_BITS_PER_DWORD_LOG2 6 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 8 +#define PR_ALIGN_OF_INT64 8 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_DOUBLE 8 +#define PR_ALIGN_OF_POINTER 8 +#define PR_ALIGN_OF_WORD 8 +#define PR_ALIGN_OF_DWORD 8 + +#else /* IS_64 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 @@ -96,6 +146,8 @@ #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 +#endif /* IS_64 */ + #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE diff --git a/base/third_party/nspr/prcpucfg_nacl.h b/base/third_party/nspr/prcpucfg_nacl.h new file mode 100644 index 0000000..d8602d3 --- /dev/null +++ b/base/third_party/nspr/prcpucfg_nacl.h @@ -0,0 +1,246 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nspr_cpucfg___ +#define nspr_cpucfg___ + +#ifndef XP_UNIX +#define XP_UNIX +#endif + +#ifndef LINUX +#define LINUX +#endif + +#define PR_AF_INET6 10 /* same as AF_INET6 */ + +#if defined(__x86_64__) + +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN +#define IS_64 + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_DOUBLE 8 +#define PR_BYTES_PER_WORD 8 +#define PR_BYTES_PER_DWORD 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_DOUBLE 64 +#define PR_BITS_PER_WORD 64 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_DOUBLE_LOG2 6 +#define PR_BITS_PER_WORD_LOG2 6 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 8 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_DOUBLE 8 +#define PR_ALIGN_OF_POINTER 8 +#define PR_ALIGN_OF_WORD 8 + +#define PR_BYTES_PER_WORD_LOG2 3 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#elif defined(__i386__) + +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_DOUBLE 8 +#define PR_BYTES_PER_WORD 4 +#define PR_BYTES_PER_DWORD 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_DOUBLE 64 +#define PR_BITS_PER_WORD 32 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_DOUBLE_LOG2 6 +#define PR_BITS_PER_WORD_LOG2 5 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 4 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_DOUBLE 4 +#define PR_ALIGN_OF_POINTER 4 +#define PR_ALIGN_OF_WORD 4 + +#define PR_BYTES_PER_WORD_LOG2 2 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#elif defined(__arm__) + +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_DOUBLE 8 +#define PR_BYTES_PER_WORD 4 +#define PR_BYTES_PER_DWORD 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_DOUBLE 64 +#define PR_BITS_PER_WORD 32 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_DOUBLE_LOG2 6 +#define PR_BITS_PER_WORD_LOG2 5 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 4 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_DOUBLE 4 +#define PR_ALIGN_OF_POINTER 4 +#define PR_ALIGN_OF_WORD 4 + +#define PR_BYTES_PER_WORD_LOG2 2 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#else + +#error "Unknown CPU architecture" + +#endif + +#define HAVE_LONG_LONG +#if PR_ALIGN_OF_DOUBLE == 8 +#define HAVE_ALIGNED_DOUBLES +#endif +#if PR_ALIGN_OF_INT64 == 8 +#define HAVE_ALIGNED_LONGLONGS +#endif + +#ifndef NO_NSPR_10_SUPPORT + +#define BYTES_PER_BYTE PR_BYTES_PER_BYTE +#define BYTES_PER_SHORT PR_BYTES_PER_SHORT +#define BYTES_PER_INT PR_BYTES_PER_INT +#define BYTES_PER_INT64 PR_BYTES_PER_INT64 +#define BYTES_PER_LONG PR_BYTES_PER_LONG +#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT +#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE +#define BYTES_PER_WORD PR_BYTES_PER_WORD +#define BYTES_PER_DWORD PR_BYTES_PER_DWORD + +#define BITS_PER_BYTE PR_BITS_PER_BYTE +#define BITS_PER_SHORT PR_BITS_PER_SHORT +#define BITS_PER_INT PR_BITS_PER_INT +#define BITS_PER_INT64 PR_BITS_PER_INT64 +#define BITS_PER_LONG PR_BITS_PER_LONG +#define BITS_PER_FLOAT PR_BITS_PER_FLOAT +#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE +#define BITS_PER_WORD PR_BITS_PER_WORD + +#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 +#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 +#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 +#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 +#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 +#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 +#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 +#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 + +#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT +#define ALIGN_OF_INT PR_ALIGN_OF_INT +#define ALIGN_OF_LONG PR_ALIGN_OF_LONG +#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 +#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT +#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE +#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER +#define ALIGN_OF_WORD PR_ALIGN_OF_WORD + +#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 +#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 +#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 + +#endif /* NO_NSPR_10_SUPPORT */ + +#endif /* nspr_cpucfg___ */ diff --git a/base/third_party/nspr/prtime.cc b/base/third_party/nspr/prtime.cc index 65f93ee..f1fcf26 100644 --- a/base/third_party/nspr/prtime.cc +++ b/base/third_party/nspr/prtime.cc @@ -1,4 +1,4 @@ -/* Portions are Copyright (C) 2007 Google Inc */ +/* Portions are Copyright (C) 2011 Google Inc */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -63,6 +63,7 @@ * 3. prlong.h */ +#include "base/logging.h" #include "base/third_party/nspr/prtime.h" #include "build/build_config.h" diff --git a/base/third_party/nspr/prtime.h b/base/third_party/nspr/prtime.h index dd75cbc..a207021 100644 --- a/base/third_party/nspr/prtime.h +++ b/base/third_party/nspr/prtime.h @@ -1,4 +1,4 @@ -/* Portions are Copyright (C) 2007 Google Inc */ +/* Portions are Copyright (C) 2011 Google Inc */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -52,7 +52,7 @@ #ifndef BASE_PRTIME_H__ #define BASE_PRTIME_H__ -#include "base/logging.h" +#include "base/base_api.h" #include "base/third_party/nspr/prtypes.h" #define PR_ASSERT DCHECK @@ -225,7 +225,12 @@ NSPR_API(PRTimeParameters) PR_GMTParameters(const PRExplodedTime *gmt); * the time string which you are parsing. */ -NSPR_API(PRStatus) PR_ParseTimeString ( +/* + * This is the only funtion that should be called from outside base, and only + * from the unit test. + */ + +BASE_API PRStatus PR_ParseTimeString ( const char *string, PRBool default_to_gmt, PRTime *result); diff --git a/base/third_party/nspr/prtypes.h b/base/third_party/nspr/prtypes.h index 3453144..630df81 100644 --- a/base/third_party/nspr/prtypes.h +++ b/base/third_party/nspr/prtypes.h @@ -135,55 +135,6 @@ #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x -#elif defined(WIN16) - -#define PR_CALLBACK_DECL __cdecl - -#if defined(_WINDLL) -#define PR_EXPORT(__type) extern __type _cdecl _export _loadds -#define PR_IMPORT(__type) extern __type _cdecl _export _loadds -#define PR_EXPORT_DATA(__type) extern __type _export -#define PR_IMPORT_DATA(__type) extern __type _export - -#define PR_EXTERN(__type) extern __type _cdecl _export _loadds -#define PR_IMPLEMENT(__type) __type _cdecl _export _loadds -#define PR_EXTERN_DATA(__type) extern __type _export -#define PR_IMPLEMENT_DATA(__type) __type _export - -#define PR_CALLBACK __cdecl __loadds -#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK - -#else /* this must be .EXE */ -#define PR_EXPORT(__type) extern __type _cdecl _export -#define PR_IMPORT(__type) extern __type _cdecl _export -#define PR_EXPORT_DATA(__type) extern __type _export -#define PR_IMPORT_DATA(__type) extern __type _export - -#define PR_EXTERN(__type) extern __type _cdecl _export -#define PR_IMPLEMENT(__type) __type _cdecl _export -#define PR_EXTERN_DATA(__type) extern __type _export -#define PR_IMPLEMENT_DATA(__type) __type _export - -#define PR_CALLBACK __cdecl __loadds -#define PR_STATIC_CALLBACK(__x) __x PR_CALLBACK -#endif /* _WINDLL */ - -#elif defined(XP_MAC) - -#define PR_EXPORT(__type) extern __declspec(export) __type -#define PR_EXPORT_DATA(__type) extern __declspec(export) __type -#define PR_IMPORT(__type) extern __declspec(export) __type -#define PR_IMPORT_DATA(__type) extern __declspec(export) __type - -#define PR_EXTERN(__type) extern __declspec(export) __type -#define PR_IMPLEMENT(__type) __declspec(export) __type -#define PR_EXTERN_DATA(__type) extern __declspec(export) __type -#define PR_IMPLEMENT_DATA(__type) __declspec(export) __type - -#define PR_CALLBACK -#define PR_CALLBACK_DECL -#define PR_STATIC_CALLBACK(__x) static __x - #elif defined(XP_OS2) && defined(__declspec) #define PR_EXPORT(__type) extern __declspec(dllexport) __type @@ -200,20 +151,26 @@ #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x -#elif defined(XP_OS2_VACPP) +#elif defined(SYMBIAN) -#define PR_EXPORT(__type) extern __type -#define PR_EXPORT_DATA(__type) extern __type -#define PR_IMPORT(__type) extern __type -#define PR_IMPORT_DATA(__type) extern __type +#define PR_EXPORT(__type) extern __declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type +#ifdef __WINS__ +#define PR_IMPORT(__type) extern __declspec(dllexport) __type +#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type +#else +#define PR_IMPORT(__type) extern __declspec(dllimport) __type +#define PR_IMPORT_DATA(__type) extern __declspec(dllimport) __type +#endif #define PR_EXTERN(__type) extern __type #define PR_IMPLEMENT(__type) __type #define PR_EXTERN_DATA(__type) extern __type #define PR_IMPLEMENT_DATA(__type) __type -#define PR_CALLBACK _Optlink + +#define PR_CALLBACK #define PR_CALLBACK_DECL -#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK +#define PR_STATIC_CALLBACK(__x) static __x #else /* Unix */ @@ -301,7 +258,7 @@ PR_BEGIN_EXTERN_C ** PRInt8 ** DESCRIPTION: ** The int8 types are known to be 8 bits each. There is no type that -** is equivalent to a plain "char". +** is equivalent to a plain "char". ************************************************************************/ #if PR_BYTES_PER_BYTE == 1 typedef unsigned char PRUint8; @@ -340,7 +297,7 @@ typedef signed char PRInt8; ** TYPES: PRUint16 ** PRInt16 ** DESCRIPTION: -** The int16 types are known to be 16 bits each. +** The int16 types are known to be 16 bits each. ************************************************************************/ #if PR_BYTES_PER_SHORT == 2 typedef unsigned short PRUint16; @@ -365,7 +322,7 @@ typedef short PRInt16; ** TYPES: PRUint32 ** PRInt32 ** DESCRIPTION: -** The int32 types are known to be 32 bits each. +** The int32 types are known to be 32 bits each. ************************************************************************/ #if PR_BYTES_PER_INT == 4 typedef unsigned int PRUint32; @@ -404,12 +361,15 @@ typedef long PRInt32; ** the LL_ macros (see prlong.h). ************************************************************************/ #ifdef HAVE_LONG_LONG -#if PR_BYTES_PER_LONG == 8 +/* Keep this in sync with prlong.h. */ +/* + * On 64-bit Mac OS X, uint64 needs to be defined as unsigned long long to + * match uint64_t, otherwise our uint64 typedef conflicts with the uint64 + * typedef in cssmconfig.h, which CoreServices.h includes indirectly. + */ +#if PR_BYTES_PER_LONG == 8 && !defined(__APPLE__) typedef long PRInt64; typedef unsigned long PRUint64; -#elif defined(WIN16) -typedef __int64 PRInt64; -typedef unsigned __int64 PRUint64; #elif defined(WIN32) && !defined(__GNUC__) typedef __int64 PRInt64; typedef unsigned __int64 PRUint64; @@ -435,7 +395,7 @@ typedef PRInt64 PRUint64; ** The PRIntn types are most appropriate for automatic variables. They are ** guaranteed to be at least 16 bits, though various architectures may ** define them to be wider (e.g., 32 or even 64 bits). These types are -** never valid for fields of a structure. +** never valid for fields of a structure. ************************************************************************/ #if PR_BYTES_PER_INT >= 2 typedef int PRIntn; @@ -447,14 +407,14 @@ typedef unsigned int PRUintn; /************************************************************************ ** TYPES: PRFloat64 ** DESCRIPTION: -** NSPR's floating point type is always 64 bits. +** NSPR's floating point type is always 64 bits. ************************************************************************/ typedef double PRFloat64; /************************************************************************ ** TYPES: PRSize ** DESCRIPTION: -** A type for representing the size of objects. +** A type for representing the size of objects. ************************************************************************/ typedef size_t PRSize; @@ -462,7 +422,7 @@ typedef size_t PRSize; /************************************************************************ ** TYPES: PROffset32, PROffset64 ** DESCRIPTION: -** A type for representing byte offsets from some location. +** A type for representing byte offsets from some location. ************************************************************************/ typedef PRInt32 PROffset32; typedef PRInt64 PROffset64; @@ -471,7 +431,7 @@ typedef PRInt64 PROffset64; ** TYPES: PRPtrDiff ** DESCRIPTION: ** A type for pointer difference. Variables of this type are suitable -** for storing a pointer or pointer subtraction. +** for storing a pointer or pointer subtraction. ************************************************************************/ typedef ptrdiff_t PRPtrdiff; @@ -479,10 +439,10 @@ typedef ptrdiff_t PRPtrdiff; ** TYPES: PRUptrdiff ** DESCRIPTION: ** A type for pointer difference. Variables of this type are suitable -** for storing a pointer or pointer sutraction. +** for storing a pointer or pointer sutraction. ************************************************************************/ #ifdef _WIN64 -typedef unsigned __int64 PRUptrdiff; +typedef PRUint64 PRUptrdiff; #else typedef unsigned long PRUptrdiff; #endif @@ -493,7 +453,7 @@ typedef unsigned long PRUptrdiff; ** Use PRBool for variables and parameter types. Use PR_FALSE and PR_TRUE ** for clarity of target type in assignments and actual arguments. Use ** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans -** just as you would C int-valued conditions. +** just as you would C int-valued conditions. ************************************************************************/ typedef PRIntn PRBool; #define PR_TRUE 1 @@ -508,14 +468,14 @@ typedef PRIntn PRBool; typedef PRUint8 PRPackedBool; /* -** Status code used by some routines that have a single point of failure or +** Status code used by some routines that have a single point of failure or ** special status return. */ typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; #ifndef __PRUNICHAR__ #define __PRUNICHAR__ -#if defined(WIN32) || defined(XP_MAC) +#ifdef WIN32 typedef wchar_t PRUnichar; #else typedef PRUint16 PRUnichar; @@ -534,8 +494,8 @@ typedef PRUint16 PRUnichar; ** http://java.sun.com/docs/books/vmspec/index.html.) */ #ifdef _WIN64 -typedef __int64 PRWord; -typedef unsigned __int64 PRUword; +typedef PRInt64 PRWord; +typedef PRUint64 PRUword; #else typedef long PRWord; typedef unsigned long PRUword; @@ -580,6 +540,14 @@ typedef unsigned long PRUword; /********* ????????????? End Fix me ?????????????????????????????? *****/ #endif /* NO_NSPR_10_SUPPORT */ +/* +** Compile-time assert. "condition" must be a constant expression. +** The macro can be used only in places where an "extern" declaration is +** allowed. +*/ +#define PR_STATIC_ASSERT(condition) \ + extern void pr_static_assert(int arg[(condition) ? 1 : -1]) + PR_END_EXTERN_C #if !defined(NO_NSPR_10_SUPPORT) diff --git a/base/threading/non_thread_safe.h b/base/threading/non_thread_safe.h index bc3be3c..e4a1c07 100644 --- a/base/threading/non_thread_safe.h +++ b/base/threading/non_thread_safe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/base/threading/non_thread_safe_impl.h b/base/threading/non_thread_safe_impl.h index 12925f1..ab0999a 100644 --- a/base/threading/non_thread_safe_impl.h +++ b/base/threading/non_thread_safe_impl.h @@ -6,6 +6,7 @@ #define BASE_THREADING_NON_THREAD_SAFE_IMPL_H_ #pragma once +#include "base/base_api.h" #include "base/threading/thread_checker_impl.h" namespace base { @@ -16,7 +17,7 @@ namespace base { // // Note: You should almost always use the NonThreadSafe class to get // the right version of the class for your build configuration. -class NonThreadSafeImpl { +class BASE_API NonThreadSafeImpl { public: ~NonThreadSafeImpl(); diff --git a/base/threading/non_thread_safe_unittest.cc b/base/threading/non_thread_safe_unittest.cc index b79a4f4..01efe28 100644 --- a/base/threading/non_thread_safe_unittest.cc +++ b/base/threading/non_thread_safe_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/basictypes.h" #include "base/logging.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/threading/non_thread_safe.h" #include "base/threading/simple_thread.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h index 0a3c75d..40d445f 100644 --- a/base/threading/platform_thread.h +++ b/base/threading/platform_thread.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,6 +10,7 @@ #define BASE_THREADING_PLATFORM_THREAD_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" #include "build/build_config.h" @@ -47,11 +48,11 @@ typedef pid_t PlatformThreadId; const PlatformThreadId kInvalidThreadId = 0; // A namespace for low-level thread functions. -class PlatformThread { +class BASE_API PlatformThread { public: // Implement this interface to run code on a background thread. Your // ThreadMain method will be called on the newly created thread. - class Delegate { + class BASE_API Delegate { public: virtual ~Delegate() {} virtual void ThreadMain() = 0; diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc index 103145a..e880222 100644 --- a/base/threading/platform_thread_posix.cc +++ b/base/threading/platform_thread_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,8 +8,8 @@ #include <sched.h> #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/safe_strerror_posix.h" -#include "base/scoped_ptr.h" #include "base/threading/thread_restrictions.h" #if defined(OS_MACOSX) diff --git a/base/threading/simple_thread.h b/base/threading/simple_thread.h index 1631336..f1b644b 100644 --- a/base/threading/simple_thread.h +++ b/base/threading/simple_thread.h @@ -45,6 +45,7 @@ #include <queue> #include <vector> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/threading/platform_thread.h" #include "base/synchronization/lock.h" @@ -54,9 +55,9 @@ namespace base { // This is the base SimpleThread. You can derive from it and implement the // virtual Run method, or you can use the DelegateSimpleThread interface. -class SimpleThread : public PlatformThread::Delegate { +class BASE_API SimpleThread : public PlatformThread::Delegate { public: - class Options { + class BASE_API Options { public: Options() : stack_size_(0) { } ~Options() { } @@ -113,9 +114,9 @@ class SimpleThread : public PlatformThread::Delegate { bool joined_; // True if Join has been called. }; -class DelegateSimpleThread : public SimpleThread { +class BASE_API DelegateSimpleThread : public SimpleThread { public: - class Delegate { + class BASE_API Delegate { public: Delegate() { } virtual ~Delegate() { } @@ -143,7 +144,8 @@ class DelegateSimpleThread : public SimpleThread { // JoinAll() will make sure that all outstanding work is processed, and wait // for everything to finish. You can reuse a pool, so you can call Start() // again after you've called JoinAll(). -class DelegateSimpleThreadPool : public DelegateSimpleThread::Delegate { +class BASE_API DelegateSimpleThreadPool + : public DelegateSimpleThread::Delegate { public: typedef DelegateSimpleThread::Delegate Delegate; diff --git a/base/threading/thread.h b/base/threading/thread.h index 379615d..034cb7d 100644 --- a/base/threading/thread.h +++ b/base/threading/thread.h @@ -8,6 +8,7 @@ #include <string> +#include "base/base_api.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/threading/platform_thread.h" @@ -25,7 +26,7 @@ namespace base { // (1) Thread::CleanUp() // (2) MessageLoop::~MessageLoop // (3.b) MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop -class Thread : PlatformThread::Delegate { +class BASE_API Thread : PlatformThread::Delegate { public: struct Options { Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {} diff --git a/base/threading/thread_checker_impl.h b/base/threading/thread_checker_impl.h index 6d41fdc..02ecebf 100644 --- a/base/threading/thread_checker_impl.h +++ b/base/threading/thread_checker_impl.h @@ -6,6 +6,7 @@ #define BASE_THREADING_THREAD_CHECKER_IMPL_H_ #pragma once +#include "base/base_api.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" @@ -17,7 +18,7 @@ namespace base { // // Note: You should almost always use the ThreadChecker class to get the // right version for your build configuration. -class ThreadCheckerImpl { +class BASE_API ThreadCheckerImpl { public: ThreadCheckerImpl(); ~ThreadCheckerImpl(); diff --git a/base/threading/thread_checker_unittest.cc b/base/threading/thread_checker_unittest.cc index 9a22a8e..2808048 100644 --- a/base/threading/thread_checker_unittest.cc +++ b/base/threading/thread_checker_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/basictypes.h" #include "base/logging.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/threading/thread_checker.h" #include "base/threading/simple_thread.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/threading/thread_collision_warner.h b/base/threading/thread_collision_warner.h index 17ed5a4..b26568d 100644 --- a/base/threading/thread_collision_warner.h +++ b/base/threading/thread_collision_warner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,7 @@ #include <memory> +#include "base/base_api.h" #include "base/atomicops.h" // A helper class alongside macros to be used to verify assumptions about thread @@ -130,17 +131,17 @@ namespace base { // AsserterBase is the interfaces and DCheckAsserter is the default asserter // used. During the unit tests is used another class that doesn't "DCHECK" // in case of collision (check thread_collision_warner_unittests.cc) -struct AsserterBase { +struct BASE_API AsserterBase { virtual ~AsserterBase() {} virtual void warn() = 0; }; -struct DCheckAsserter : public AsserterBase { +struct BASE_API DCheckAsserter : public AsserterBase { virtual ~DCheckAsserter() {} virtual void warn(); }; -class ThreadCollisionWarner { +class BASE_API ThreadCollisionWarner { public: // The parameter asserter is there only for test purpose ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter()) @@ -157,7 +158,7 @@ class ThreadCollisionWarner { // it doesn't leave the critical section, as opposed to ScopedCheck, // because the critical section being pinned is allowed to be used only // from one thread - class Check { + class BASE_API Check { public: explicit Check(ThreadCollisionWarner* warner) : warner_(warner) { @@ -174,7 +175,7 @@ class ThreadCollisionWarner { // This class is meant to be used through the macro // DFAKE_SCOPED_LOCK - class ScopedCheck { + class BASE_API ScopedCheck { public: explicit ScopedCheck(ThreadCollisionWarner* warner) : warner_(warner) { @@ -193,7 +194,7 @@ class ThreadCollisionWarner { // This class is meant to be used through the macro // DFAKE_SCOPED_RECURSIVE_LOCK - class ScopedRecursiveCheck { + class BASE_API ScopedRecursiveCheck { public: explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner) : warner_(warner) { diff --git a/base/threading/thread_collision_warner_unittest.cc b/base/threading/thread_collision_warner_unittest.cc index a3d3b66..4613955 100644 --- a/base/threading/thread_collision_warner_unittest.cc +++ b/base/threading/thread_collision_warner_unittest.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/compiler_specific.h" -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" #include "base/threading/simple_thread.h" diff --git a/base/threading/thread_local.h b/base/threading/thread_local.h index 069543f..4bacf92 100644 --- a/base/threading/thread_local.h +++ b/base/threading/thread_local.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -49,6 +49,7 @@ #define BASE_THREADING_THREAD_LOCAL_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" #if defined(OS_POSIX) @@ -60,7 +61,7 @@ namespace base { namespace internal { // Helper functions that abstract the cross-platform APIs. Do not use directly. -struct ThreadLocalPlatform { +struct BASE_API ThreadLocalPlatform { #if defined(OS_WIN) typedef unsigned long SlotType; #elif defined(OS_POSIX) diff --git a/base/threading/thread_local_storage.h b/base/threading/thread_local_storage.h index 204b653..f882729 100644 --- a/base/threading/thread_local_storage.h +++ b/base/threading/thread_local_storage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #define BASE_THREADING_THREAD_LOCAL_STORAGE_H_ #pragma once +#include "base/base_api.h" #include "base/basictypes.h" #if defined(OS_POSIX) @@ -16,7 +17,7 @@ namespace base { // Wrapper for thread local storage. This class doesn't do much except provide // an API for portability. -class ThreadLocalStorage { +class BASE_API ThreadLocalStorage { public: // Prototype for the TLS destructor function, which can be optionally used to @@ -25,7 +26,7 @@ class ThreadLocalStorage { typedef void (*TLSDestructorFunc)(void* value); // A key representing one value stored in TLS. - class Slot { + class BASE_API Slot { public: explicit Slot(TLSDestructorFunc destructor = NULL); diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index de8174f..98e0422 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h @@ -1,10 +1,11 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_THREADING_THREAD_RESTRICTIONS_H_ #define BASE_THREADING_THREAD_RESTRICTIONS_H_ +#include "base/base_api.h" #include "base/basictypes.h" namespace base { @@ -35,11 +36,11 @@ namespace base { // only calls other functions in Chrome and not fopen(), you should go // add the AssertIOAllowed checks in the helper functions. -class ThreadRestrictions { +class BASE_API ThreadRestrictions { public: // Constructing a ScopedAllowIO temporarily allows IO for the current // thread. Doing this is almost certainly always incorrect. - class ScopedAllowIO { + class BASE_API ScopedAllowIO { public: ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } ~ScopedAllowIO() { SetIOAllowed(previous_value_); } @@ -52,7 +53,7 @@ class ThreadRestrictions { // Constructing a ScopedAllowSingleton temporarily allows accessing for the // current thread. Doing this is almost always incorrect. - class ScopedAllowSingleton { + class BASE_API ScopedAllowSingleton { public: ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); } ~ScopedAllowSingleton() { SetSingletonAllowed(previous_value_); } diff --git a/base/threading/watchdog.h b/base/threading/watchdog.h index 4af45dc..fafda43 100644 --- a/base/threading/watchdog.h +++ b/base/threading/watchdog.h @@ -21,6 +21,7 @@ #include <string> +#include "base/base_api.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" @@ -28,7 +29,7 @@ namespace base { -class Watchdog { +class BASE_API Watchdog { public: // Constructor specifies how long the Watchdog will wait before alarming. Watchdog(const TimeDelta& duration, diff --git a/base/threading/worker_pool.h b/base/threading/worker_pool.h index 9a02acc..12b50b4 100644 --- a/base/threading/worker_pool.h +++ b/base/threading/worker_pool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #define BASE_THREADING_WORKER_POOL_H_ #pragma once +#include "base/base_api.h" #include "base/tracked.h" class Task; @@ -20,7 +21,7 @@ namespace base { // inside the pool must be extremely careful about other objects they access // (MessageLoops, Singletons, etc). During shutdown these object may no longer // exist. -class WorkerPool { +class BASE_API WorkerPool { public: // This function posts |task| to run on a worker thread. |task_is_slow| // should be used for tasks that will take a long time to execute. Returns diff --git a/base/threading/worker_pool_posix.cc b/base/threading/worker_pool_posix.cc index 8466403..bd6210f 100644 --- a/base/threading/worker_pool_posix.cc +++ b/base/threading/worker_pool_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" #include "base/stringprintf.h" #include "base/task.h" #include "base/threading/platform_thread.h" diff --git a/base/threading/worker_pool_posix.h b/base/threading/worker_pool_posix.h index 1b68aef..701157a 100644 --- a/base/threading/worker_pool_posix.h +++ b/base/threading/worker_pool_posix.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -29,8 +29,8 @@ #include <string> #include "base/basictypes.h" -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" diff --git a/base/time.h b/base/time.h index ed4e772..cc99faa 100644 --- a/base/time.h +++ b/base/time.h @@ -25,6 +25,7 @@ #include <time.h> +#include "base/base_api.h" #include "base/basictypes.h" #if defined(OS_POSIX) @@ -48,7 +49,7 @@ class PageLoadTrackerUnitTest; // TimeDelta ------------------------------------------------------------------ -class TimeDelta { +class BASE_API TimeDelta { public: TimeDelta() : delta_(0) { } @@ -178,7 +179,7 @@ inline TimeDelta operator*(int64 a, TimeDelta td) { // Time ----------------------------------------------------------------------- // Represents a wall clock time. -class Time { +class BASE_API Time { public: static const int64 kMillisecondsPerSecond = 1000; static const int64 kMicrosecondsPerMillisecond = 1000; @@ -204,7 +205,7 @@ class Time { // Represents an exploded time that can be formatted nicely. This is kind of // like the Win32 SYSTEMTIME structure or the Unix "struct tm" with a few // additions and changes to prevent errors. - struct Exploded { + struct BASE_API Exploded { int year; // Four digit year "2007" int month; // 1-based month (values 1 = January, etc.) int day_of_week; // 0-based day of week (0 = Sunday, etc.) @@ -449,7 +450,7 @@ inline Time TimeDelta::operator+(Time t) const { // TimeTicks ------------------------------------------------------------------ -class TimeTicks { +class BASE_API TimeTicks { public: TimeTicks() : ticks_(0) { } diff --git a/base/time_posix.cc b/base/time_posix.cc index 62e6e49..4b29cea 100644 --- a/base/time_posix.cc +++ b/base/time_posix.cc @@ -109,8 +109,10 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this timestruct.tm_yday = 0; // mktime/timegm ignore this timestruct.tm_isdst = -1; // attempt to figure it out +#if !defined(OS_NACL) timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore +#endif time_t seconds; if (is_local) @@ -179,6 +181,15 @@ TimeTicks TimeTicks::Now() { return TimeTicks(absolute_micro); } +#elif defined(OS_NACL) + +TimeTicks TimeTicks::Now() { + // Sadly, Native Client does not have _POSIX_TIMERS enabled in sys/features.h + // Apparently NaCl only has CLOCK_REALTIME: + // http://code.google.com/p/nativeclient/issues/detail?id=1159 + return TimeTicks(clock()); +} + #else // _POSIX_MONOTONIC_CLOCK #error No usable tick clock function on this platform. #endif // _POSIX_MONOTONIC_CLOCK diff --git a/base/time_win.cc b/base/time_win.cc index 601211c..883c486 100644 --- a/base/time_win.cc +++ b/base/time_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -43,7 +43,7 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/cpu.h" -#include "base/singleton.h" +#include "base/memory/singleton.h" #include "base/synchronization/lock.h" using base::Time; diff --git a/base/timer.h b/base/timer.h index 0de7c79..6fe826a 100644 --- a/base/timer.h +++ b/base/timer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -47,6 +47,7 @@ // because they're flaky on the buildbot, but when you run them locally you // should be able to tell the difference. +#include "base/base_api.h" #include "base/logging.h" #include "base/task.h" #include "base/time.h" @@ -61,7 +62,7 @@ namespace base { // // This class exists to share code between BaseTimer<T> template instantiations. // -class BaseTimer_Helper { +class BASE_API BaseTimer_Helper { public: // Stops the timer. ~BaseTimer_Helper() { @@ -232,7 +233,7 @@ class DelayTimer { private: void DelayFor(TimeDelta delay) { - trigger_time_ = Time::Now() + delay; + trigger_time_ = TimeTicks::Now() + delay; // If we already have a timer that will expire at or before the given delay, // then we have nothing more to do now. @@ -249,7 +250,7 @@ class DelayTimer { return; // If we have not waited long enough, then wait some more. - const Time now = Time::Now(); + const TimeTicks now = TimeTicks::Now(); if (now < trigger_time_) { DelayFor(trigger_time_ - now); return; @@ -263,7 +264,7 @@ class DelayTimer { const TimeDelta delay_; OneShotTimer<DelayTimer<Receiver> > timer_; - Time trigger_time_; + TimeTicks trigger_time_; }; } // namespace base diff --git a/base/timer_unittest.cc b/base/timer_unittest.cc index c2289c8..79d3a4e 100644 --- a/base/timer_unittest.cc +++ b/base/timer_unittest.cc @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/scoped_ptr.h" #include "base/message_loop.h" -#include "base/scoped_ptr.h" #include "base/task.h" #include "base/timer.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/tracked.h b/base/tracked.h index b4f6e36..45776d1 100644 --- a/base/tracked.h +++ b/base/tracked.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -21,6 +21,7 @@ #include <string> +#include "base/base_api.h" #include "base/time.h" #ifndef NDEBUG @@ -35,7 +36,7 @@ namespace tracked_objects { // Location provides basic info where of an object was constructed, or was // significantly brought to life. -class Location { +class BASE_API Location { public: // Constructor should be called with a long-lived char*, such as __FILE__. // It assumes the provided value will persist as a global constant, and it @@ -87,7 +88,7 @@ class Location { class Births; -class Tracked { +class BASE_API Tracked { public: Tracked(); virtual ~Tracked(); diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc index d10603d..b5fc146 100644 --- a/base/tracked_objects.cc +++ b/base/tracked_objects.cc @@ -452,7 +452,7 @@ void ThreadData::RunOnAllThreads(void (*function)()) { int ret_val = CloseHandle(completion_handle); DCHECK(ret_val); } -#endif +#endif // OS_WIN // static bool ThreadData::StartTracking(bool status) { diff --git a/base/tracked_objects.h b/base/tracked_objects.h index ac49225..99b5ed2 100644 --- a/base/tracked_objects.h +++ b/base/tracked_objects.h @@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/synchronization/lock.h" #include "base/tracked.h" #include "base/threading/thread_local_storage.h" @@ -156,7 +157,7 @@ namespace tracked_objects { // For a specific thread, and a specific birth place, the collection of all // death info (with tallies for each death thread, to prevent access conflicts). class ThreadData; -class BirthOnThread { +class BASE_API BirthOnThread { public: explicit BirthOnThread(const Location& location); @@ -179,7 +180,7 @@ class BirthOnThread { //------------------------------------------------------------------------------ // A class for accumulating counts of births (without bothering with a map<>). -class Births: public BirthOnThread { +class BASE_API Births: public BirthOnThread { public: explicit Births(const Location& location); @@ -207,7 +208,7 @@ class Births: public BirthOnThread { // birthplace (fixed Location). Used both on specific threads, and also used // in snapshots when integrating assembled data. -class DeathData { +class BASE_API DeathData { public: // Default initializer. DeathData() : count_(0), square_duration_(0) {} @@ -248,7 +249,7 @@ class DeathData { // The source of this data was collected on many threads, and is asynchronously // changing. The data in this instance is not asynchronously changing. -class Snapshot { +class BASE_API Snapshot { public: // When snapshotting a full life cycle set (birth-to-death), use this: Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread, @@ -284,7 +285,7 @@ class Snapshot { // items. It protects the gathering under locks, so that it could be called via // Posttask on any threads, or passed to all the target threads in parallel. -class DataCollector { +class BASE_API DataCollector { public: typedef std::vector<Snapshot> Collection; @@ -331,7 +332,7 @@ class DataCollector { // Aggregation contains summaries (totals and subtotals) of groups of Snapshot // instances to provide printing of these collections on a single line. -class Aggregation: public DeathData { +class BASE_API Aggregation: public DeathData { public: Aggregation(); ~Aggregation(); @@ -357,13 +358,13 @@ class Aggregation: public DeathData { //------------------------------------------------------------------------------ // Comparator is a class that supports the comparison of Snapshot instances. // An instance is actually a list of chained Comparitors, that can provide for -// arbitrary ordering. The path portion of an about:objects URL is translated +// arbitrary ordering. The path portion of an about:tasks URL is translated // into such a chain, which is then used to order Snapshot instances in a // vector. It orders them into groups (for aggregation), and can also order // instances within the groups (for detailed rendering of the instances in an // aggregation). -class Comparator { +class BASE_API Comparator { public: // Selector enum is the token identifier for each parsed keyword, most of // which specify a sort order. @@ -423,7 +424,7 @@ class Comparator { // Translate a keyword and restriction in URL path to a selector for sorting. void ParseKeyphrase(const std::string& key_phrase); - // Parse a query in an about:objects URL to decide on sort ordering. + // Parse a query in an about:tasks URL to decide on sort ordering. bool ParseQuery(const std::string& query); // Output a header line that can be used to indicated what items will be @@ -464,7 +465,7 @@ class Comparator { // For each thread, we have a ThreadData that stores all tracking info generated // on this thread. This prevents the need for locking as data accumulates. -class ThreadData { +class BASE_API ThreadData { public: typedef std::map<Location, Births*> BirthMap; typedef std::map<const Births*, DeathData> DeathMap; @@ -479,8 +480,7 @@ class ThreadData { // return null. static ThreadData* current(); - // For a given about:objects URL, develop resulting HTML, and append to - // output. + // For a given about:tasks URL, develop resulting HTML, and append to output. static void WriteHTML(const std::string& query, std::string* output); // For a given accumulated array of results, use the comparator to sort and @@ -505,7 +505,7 @@ class ThreadData { // Using our lock, make a copy of the specified maps. These calls may arrive // from non-local threads, and are used to quickly scan data from all threads - // in order to build an HTML page for about:objects. + // in order to build an HTML page for about:tasks. void SnapshotBirthMap(BirthMap *output) const; void SnapshotDeathMap(DeathMap *output) const; diff --git a/base/utf_offset_string_conversions.cc b/base/utf_offset_string_conversions.cc index 4c47ef8..6f51ca9 100644 --- a/base/utf_offset_string_conversions.cc +++ b/base/utf_offset_string_conversions.cc @@ -1,9 +1,12 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/utf_offset_string_conversions.h" +#include <algorithm> + +#include "base/scoped_ptr.h" #include "base/string_piece.h" #include "base/utf_string_conversion_utils.h" @@ -21,13 +24,16 @@ template<typename SRC_CHAR> bool ConvertUnicode(const SRC_CHAR* src, size_t src_len, std::wstring* output, - size_t* offset_for_adjustment) { - size_t output_offset = - (offset_for_adjustment && *offset_for_adjustment < src_len) ? - *offset_for_adjustment : std::wstring::npos; + std::vector<size_t>* offsets_for_adjustment) { + if (offsets_for_adjustment) { + std::for_each(offsets_for_adjustment->begin(), + offsets_for_adjustment->end(), + LimitOffset<std::wstring>(src_len)); + } // ICU requires 32-bit numbers. bool success = true; + AdjustOffset::Adjustments adjustments; int32 src_len32 = static_cast<int32>(src_len); for (int32 i = 0; i < src_len32; i++) { uint32 code_point; @@ -39,21 +45,23 @@ bool ConvertUnicode(const SRC_CHAR* src, chars_written = WriteUnicodeCharacter(0xFFFD, output); success = false; } - if ((output_offset != std::wstring::npos) && - (*offset_for_adjustment > original_i)) { + if (offsets_for_adjustment) { // NOTE: ReadUnicodeCharacter() adjusts |i| to point _at_ the last // character read, not after it (so that incrementing it in the loop // increment will place it at the right location), so we need to account // for that in determining the amount that was read. - if (*offset_for_adjustment <= static_cast<size_t>(i)) - output_offset = std::wstring::npos; - else - output_offset += chars_written - (i - original_i + 1); + adjustments.push_back(AdjustOffset::Adjustment( + original_i, i - original_i + 1, chars_written)); } } - if (offset_for_adjustment) - *offset_for_adjustment = output_offset; + // Make offset adjustment. + if (offsets_for_adjustment && !adjustments.empty()) { + std::for_each(offsets_for_adjustment->begin(), + offsets_for_adjustment->end(), + AdjustOffset(adjustments)); + } + return success; } @@ -63,16 +71,44 @@ bool UTF8ToWideAndAdjustOffset(const char* src, size_t src_len, std::wstring* output, size_t* offset_for_adjustment) { + std::vector<size_t> offsets; + if (offset_for_adjustment) + offsets.push_back(*offset_for_adjustment); PrepareForUTF16Or32Output(src, src_len, output); - return ConvertUnicode(src, src_len, output, offset_for_adjustment); + bool ret = ConvertUnicode(src, src_len, output, &offsets); + if (offset_for_adjustment) + *offset_for_adjustment = offsets[0]; + return ret; +} + +bool UTF8ToWideAndAdjustOffsets(const char* src, + size_t src_len, + std::wstring* output, + std::vector<size_t>* offsets_for_adjustment) { + PrepareForUTF16Or32Output(src, src_len, output); + return ConvertUnicode(src, src_len, output, offsets_for_adjustment); } std::wstring UTF8ToWideAndAdjustOffset(const base::StringPiece& utf8, size_t* offset_for_adjustment) { - std::wstring ret; - UTF8ToWideAndAdjustOffset(utf8.data(), utf8.length(), &ret, - offset_for_adjustment); - return ret; + std::vector<size_t> offsets; + if (offset_for_adjustment) + offsets.push_back(*offset_for_adjustment); + std::wstring result; + UTF8ToWideAndAdjustOffsets(utf8.data(), utf8.length(), &result, + &offsets); + if (offset_for_adjustment) + *offset_for_adjustment = offsets[0]; + return result; +} + +std::wstring UTF8ToWideAndAdjustOffsets(const base::StringPiece& utf8, + std::vector<size_t>* + offsets_for_adjustment) { + std::wstring result; + UTF8ToWideAndAdjustOffsets(utf8.data(), utf8.length(), &result, + offsets_for_adjustment); + return result; } // UTF-16 <-> Wide ------------------------------------------------------------- @@ -90,6 +126,19 @@ bool UTF16ToWideAndAdjustOffset(const char16* src, return true; } +bool UTF16ToWideAndAdjustOffsets(const char16* src, + size_t src_len, + std::wstring* output, + std::vector<size_t>* offsets_for_adjustment) { + output->assign(src, src_len); + if (offsets_for_adjustment) { + std::for_each(offsets_for_adjustment->begin(), + offsets_for_adjustment->end(), + LimitOffset<std::wstring>(src_len)); + } + return true; +} + std::wstring UTF16ToWideAndAdjustOffset(const string16& utf16, size_t* offset_for_adjustment) { if (offset_for_adjustment && (*offset_for_adjustment >= utf16.length())) @@ -97,25 +146,99 @@ std::wstring UTF16ToWideAndAdjustOffset(const string16& utf16, return utf16; } +std::wstring UTF16ToWideAndAdjustOffsets( + const string16& utf16, + std::vector<size_t>* offsets_for_adjustment) { + if (offsets_for_adjustment) { + std::for_each(offsets_for_adjustment->begin(), + offsets_for_adjustment->end(), + LimitOffset<std::wstring>(utf16.length())); + } + return utf16; +} + #elif defined(WCHAR_T_IS_UTF32) bool UTF16ToWideAndAdjustOffset(const char16* src, size_t src_len, std::wstring* output, size_t* offset_for_adjustment) { + std::vector<size_t> offsets; + if (offset_for_adjustment) + offsets.push_back(*offset_for_adjustment); output->clear(); // Assume that normally we won't have any non-BMP characters so the counts // will be the same. output->reserve(src_len); - return ConvertUnicode(src, src_len, output, offset_for_adjustment); + bool ret = ConvertUnicode(src, src_len, output, &offsets); + if (offset_for_adjustment) + *offset_for_adjustment = offsets[0]; + return ret; +} + +bool UTF16ToWideAndAdjustOffsets(const char16* src, + size_t src_len, + std::wstring* output, + std::vector<size_t>* offsets_for_adjustment) { + output->clear(); + // Assume that normally we won't have any non-BMP characters so the counts + // will be the same. + output->reserve(src_len); + return ConvertUnicode(src, src_len, output, offsets_for_adjustment); } std::wstring UTF16ToWideAndAdjustOffset(const string16& utf16, size_t* offset_for_adjustment) { - std::wstring ret; - UTF16ToWideAndAdjustOffset(utf16.data(), utf16.length(), &ret, - offset_for_adjustment); - return ret; + std::vector<size_t> offsets; + if (offset_for_adjustment) + offsets.push_back(*offset_for_adjustment); + std::wstring result; + UTF16ToWideAndAdjustOffsets(utf16.data(), utf16.length(), &result, + &offsets); + if (offset_for_adjustment) + *offset_for_adjustment = offsets[0]; + return result; +} + +std::wstring UTF16ToWideAndAdjustOffsets( + const string16& utf16, + std::vector<size_t>* offsets_for_adjustment) { + std::wstring result; + UTF16ToWideAndAdjustOffsets(utf16.data(), utf16.length(), &result, + offsets_for_adjustment); + return result; } #endif // defined(WCHAR_T_IS_UTF32) + +AdjustOffset::Adjustment::Adjustment(size_t location, + size_t old_length, + size_t new_length) + : location(location), + old_length(old_length), + new_length(new_length) {} + +AdjustOffset::AdjustOffset(const Adjustments& adjustments) + : adjustments_(adjustments) {} + +void AdjustOffset::operator()(size_t& offset) { + if (offset == std::wstring::npos) + return; + size_t adjustment = 0; + for (Adjustments::const_iterator i = adjustments_.begin(); + i != adjustments_.end(); ++i) { + size_t location = i->location; + if (offset == location && i->new_length == 0) { + offset = std::wstring::npos; + return; + } + if (offset <= location) + break; + if (offset < (location + i->old_length)) { + offset = std::wstring::npos; + return; + } + adjustment += (i->old_length - i->new_length); + } + offset -= adjustment; +} diff --git a/base/utf_offset_string_conversions.h b/base/utf_offset_string_conversions.h index b20e4b1..152eda3 100644 --- a/base/utf_offset_string_conversions.h +++ b/base/utf_offset_string_conversions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,30 +7,92 @@ #pragma once #include <string> +#include <vector> +#include "base/base_api.h" #include "base/string16.h" namespace base { class StringPiece; } -// Like the conversions in utf_string_conversions.h, but also take offsets into -// the source strings, which will be adjusted to point at the same logical place -// in the result strings. If this isn't possible because the offsets point past -// the end of the source strings or into the middle of multibyte sequences, they -// will be set to std::wstring::npos. |offset_for_adjustment| may be NULL. -bool UTF8ToWideAndAdjustOffset(const char* src, - size_t src_len, - std::wstring* output, - size_t* offset_for_adjustment); -std::wstring UTF8ToWideAndAdjustOffset(const base::StringPiece& utf8, - size_t* offset_for_adjustment); - -bool UTF16ToWideAndAdjustOffset(const char16* src, - size_t src_len, - std::wstring* output, - size_t* offset_for_adjustment); -std::wstring UTF16ToWideAndAdjustOffset(const string16& utf16, +// Like the conversions in utf_string_conversions.h, but also takes one or more +// offsets (|offset[s]_for_adjustment|) into the source strings, each offset +// will be adjusted to point at the same logical place in the result strings. +// If this isn't possible because an offset points past the end of the source +// strings or into the middle of a multibyte sequence, the offending offset will +// be set to std::wstring::npos. |offset[s]_for_adjustment| may be NULL. +BASE_API bool UTF8ToWideAndAdjustOffset(const char* src, + size_t src_len, + std::wstring* output, size_t* offset_for_adjustment); +BASE_API bool UTF8ToWideAndAdjustOffsets( + const char* src, + size_t src_len, + std::wstring* output, + std::vector<size_t>* offsets_for_adjustment); + +BASE_API std::wstring UTF8ToWideAndAdjustOffset(const base::StringPiece& utf8, + size_t* offset_for_adjustment); +BASE_API std::wstring UTF8ToWideAndAdjustOffsets( + const base::StringPiece& utf8, + std::vector<size_t>* offsets_for_adjustment); + +BASE_API bool UTF16ToWideAndAdjustOffset(const char16* src, + size_t src_len, + std::wstring* output, + size_t* offset_for_adjustment); +BASE_API bool UTF16ToWideAndAdjustOffsets( + const char16* src, + size_t src_len, + std::wstring* output, + std::vector<size_t>* offsets_for_adjustment); + +BASE_API std::wstring UTF16ToWideAndAdjustOffset(const string16& utf16, + size_t* offset_for_adjustment); +BASE_API std::wstring UTF16ToWideAndAdjustOffsets( + const string16& utf16, + std::vector<size_t>* offsets_for_adjustment); + +// Limiting function callable by std::for_each which will replace any value +// which is equal to or greater than |limit| with npos. +template <typename T> +struct LimitOffset { + explicit LimitOffset(size_t limit) + : limit_(limit) {} + + void operator()(size_t& offset) { + if (offset >= limit_) + offset = T::npos; + } + + size_t limit_; +}; + +// Adjustment function called by std::transform which will adjust any offset +// that occurs after one or more modified substrings. To use, create any +// number of AdjustOffset::Adjustments, drop them into a vector, then call +// std::transform with the transform function being something similar to +// AdjustOffset(adjustments). Each Adjustment gives the original |location| +// of the encoded section and the |old_length| and |new_length| of the section +// before and after decoding. +struct AdjustOffset { + // Helper structure which indicates where an encoded character occurred + // and how long that encoding was. + struct Adjustment { + Adjustment(size_t location, size_t old_length, size_t new_length); + + size_t location; + size_t old_length; + size_t new_length; + }; + + typedef std::vector<Adjustment> Adjustments; + + explicit AdjustOffset(const Adjustments& adjustments); + void operator()(size_t& offset); + + const Adjustments& adjustments_; +}; #endif // BASE_UTF_OFFSET_STRING_CONVERSIONS_H_ diff --git a/base/utf_offset_string_conversions_unittest.cc b/base/utf_offset_string_conversions_unittest.cc index 4f13ab3..b731b9e 100644 --- a/base/utf_offset_string_conversions_unittest.cc +++ b/base/utf_offset_string_conversions_unittest.cc @@ -1,7 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <algorithm> + #include "base/logging.h" #include "base/string_piece.h" #include "base/utf_offset_string_conversions.h" @@ -11,6 +13,8 @@ namespace base { namespace { +static const size_t kNpos = std::wstring::npos; + // Given a null-terminated string of wchar_t with each wchar_t representing // a UTF-16 code unit, returns a string16 made up of wchar_t's in the input. // Each wchar_t should be <= 0xFFFF and a non-BMP character (> U+FFFF) @@ -40,12 +44,12 @@ TEST(UTFOffsetStringConversionsTest, AdjustOffset) { size_t input_offset; size_t output_offset; } utf8_to_wide_cases[] = { - {"", 0, std::wstring::npos}, - {"\xe4\xbd\xa0\xe5\xa5\xbd", 1, std::wstring::npos}, + {"", 0, kNpos}, + {"\xe4\xbd\xa0\xe5\xa5\xbd", 1, kNpos}, {"\xe4\xbd\xa0\xe5\xa5\xbd", 3, 1}, {"\xed\xb0\x80z", 3, 1}, {"A\xF0\x90\x8C\x80z", 1, 1}, - {"A\xF0\x90\x8C\x80z", 2, std::wstring::npos}, + {"A\xF0\x90\x8C\x80z", 2, kNpos}, #if defined(WCHAR_T_IS_UTF16) {"A\xF0\x90\x8C\x80z", 5, 3}, #elif defined(WCHAR_T_IS_UTF32) @@ -65,7 +69,7 @@ TEST(UTFOffsetStringConversionsTest, AdjustOffset) { size_t output_offset; } utf16_to_wide_cases[] = { {L"\xD840\xDC00\x4E00", 0, 0}, - {L"\xD840\xDC00\x4E00", 1, std::wstring::npos}, + {L"\xD840\xDC00\x4E00", 1, kNpos}, {L"\xD840\xDC00\x4E00", 2, 1}, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(utf16_to_wide_cases); ++i) { @@ -77,4 +81,84 @@ TEST(UTFOffsetStringConversionsTest, AdjustOffset) { #endif } +TEST(UTFOffsetStringConversionsTest, LimitOffsets) { + const size_t kLimit = 10; + const size_t kItems = 20; + std::vector<size_t> size_ts; + for (size_t t = 0; t < kItems; ++t) + size_ts.push_back(t); + std::for_each(size_ts.begin(), size_ts.end(), + LimitOffset<std::wstring>(kLimit)); + size_t unlimited_count = 0; + for (std::vector<size_t>::iterator ti = size_ts.begin(); ti != size_ts.end(); + ++ti) { + if (*ti < kLimit && *ti != kNpos) + ++unlimited_count; + } + EXPECT_EQ(10U, unlimited_count); + + // Reverse the values in the vector and try again. + size_ts.clear(); + for (size_t t = kItems; t > 0; --t) + size_ts.push_back(t - 1); + std::for_each(size_ts.begin(), size_ts.end(), + LimitOffset<std::wstring>(kLimit)); + unlimited_count = 0; + for (std::vector<size_t>::iterator ti = size_ts.begin(); ti != size_ts.end(); + ++ti) { + if (*ti < kLimit && *ti != kNpos) + ++unlimited_count; + } + EXPECT_EQ(10U, unlimited_count); +} + +TEST(UTFOffsetStringConversionsTest, AdjustOffsets) { + // Imagine we have strings as shown in the following cases where the + // X's represent encoded characters. + // 1: abcXXXdef ==> abcXdef + std::vector<size_t> offsets; + for (size_t t = 0; t < 9; ++t) + offsets.push_back(t); + AdjustOffset::Adjustments adjustments; + adjustments.push_back(AdjustOffset::Adjustment(3, 3, 1)); + std::for_each(offsets.begin(), offsets.end(), AdjustOffset(adjustments)); + size_t expected_1[] = {0, 1, 2, 3, kNpos, kNpos, 4, 5, 6}; + EXPECT_EQ(offsets.size(), arraysize(expected_1)); + for (size_t i = 0; i < arraysize(expected_1); ++i) + EXPECT_EQ(expected_1[i], offsets[i]); + + // 2: XXXaXXXXbcXXXXXXXdefXXX ==> XaXXbcXXXXdefX + offsets.clear(); + for (size_t t = 0; t < 23; ++t) + offsets.push_back(t); + adjustments.clear(); + adjustments.push_back(AdjustOffset::Adjustment(0, 3, 1)); + adjustments.push_back(AdjustOffset::Adjustment(4, 4, 2)); + adjustments.push_back(AdjustOffset::Adjustment(10, 7, 4)); + adjustments.push_back(AdjustOffset::Adjustment(20, 3, 1)); + std::for_each(offsets.begin(), offsets.end(), AdjustOffset(adjustments)); + size_t expected_2[] = {0, kNpos, kNpos, 1, 2, kNpos, kNpos, kNpos, 4, 5, 6, + kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 10, 11, 12, + 13, kNpos, kNpos}; + EXPECT_EQ(offsets.size(), arraysize(expected_2)); + for (size_t i = 0; i < arraysize(expected_2); ++i) + EXPECT_EQ(expected_2[i], offsets[i]); + + // 3: XXXaXXXXbcdXXXeXX ==> aXXXXbcdXXXe + offsets.clear(); + for (size_t t = 0; t < 17; ++t) + offsets.push_back(t); + adjustments.clear(); + adjustments.push_back(AdjustOffset::Adjustment(0, 3, 0)); + adjustments.push_back(AdjustOffset::Adjustment(4, 4, 4)); + adjustments.push_back(AdjustOffset::Adjustment(11, 3, 3)); + adjustments.push_back(AdjustOffset::Adjustment(15, 2, 0)); + std::for_each(offsets.begin(), offsets.end(), AdjustOffset(adjustments)); + size_t expected_3[] = {kNpos, kNpos, kNpos, 0, 1, kNpos, kNpos, kNpos, 5, 6, + 7, 8, kNpos, kNpos, 11, kNpos, kNpos}; + EXPECT_EQ(offsets.size(), arraysize(expected_3)); + for (size_t i = 0; i < arraysize(expected_3); ++i) + EXPECT_EQ(expected_3[i], offsets[i]); +} + } // namaspace base diff --git a/base/utf_string_conversions.h b/base/utf_string_conversions.h index 4aa4d41..9e4af87 100644 --- a/base/utf_string_conversions.h +++ b/base/utf_string_conversions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,6 +8,7 @@ #include <string> +#include "base/base_api.h" #include "base/string16.h" #include "base/string_piece.h" @@ -17,20 +18,23 @@ // do the best it can and put the result in the output buffer. The versions that // return strings ignore this error and just return the best conversion // possible. -bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output); -std::string WideToUTF8(const std::wstring& wide); -bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output); -std::wstring UTF8ToWide(const base::StringPiece& utf8); - -bool WideToUTF16(const wchar_t* src, size_t src_len, string16* output); -string16 WideToUTF16(const std::wstring& wide); -bool UTF16ToWide(const char16* src, size_t src_len, std::wstring* output); -std::wstring UTF16ToWide(const string16& utf16); - -bool UTF8ToUTF16(const char* src, size_t src_len, string16* output); -string16 UTF8ToUTF16(const base::StringPiece& utf8); -bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output); -std::string UTF16ToUTF8(const string16& utf16); +BASE_API bool WideToUTF8(const wchar_t* src, size_t src_len, + std::string* output); +BASE_API std::string WideToUTF8(const std::wstring& wide); +BASE_API bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output); +BASE_API std::wstring UTF8ToWide(const base::StringPiece& utf8); + +BASE_API bool WideToUTF16(const wchar_t* src, size_t src_len, string16* output); +BASE_API string16 WideToUTF16(const std::wstring& wide); +BASE_API bool UTF16ToWide(const char16* src, size_t src_len, + std::wstring* output); +BASE_API std::wstring UTF16ToWide(const string16& utf16); + +BASE_API bool UTF8ToUTF16(const char* src, size_t src_len, string16* output); +BASE_API string16 UTF8ToUTF16(const base::StringPiece& utf8); +BASE_API bool UTF16ToUTF8(const char16* src, size_t src_len, + std::string* output); +BASE_API std::string UTF16ToUTF8(const string16& utf16); // We are trying to get rid of wstring as much as possible, but it's too big // a mess to do it all at once. These conversions should be used when we @@ -47,7 +51,7 @@ std::string UTF16ToUTF8(const string16& utf16); // These convert an ASCII string, typically a hardcoded constant, to a // UTF16/Wide string. -std::wstring ASCIIToWide(const base::StringPiece& ascii); -string16 ASCIIToUTF16(const base::StringPiece& ascii); +BASE_API std::wstring ASCIIToWide(const base::StringPiece& ascii); +BASE_API string16 ASCIIToUTF16(const base::StringPiece& ascii); #endif // BASE_UTF_STRING_CONVERSIONS_H_ diff --git a/base/value_conversions.cc b/base/value_conversions.cc new file mode 100644 index 0000000..64513d0 --- /dev/null +++ b/base/value_conversions.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/value_conversions.h" + +#include "base/file_path.h" +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" + +namespace base { + +namespace { + +// |Value| internally stores strings in UTF-8, so we have to convert from the +// system native code to UTF-8 and back. + +std::string FilePathToUTF8(const FilePath& file_path) { +#if defined(OS_POSIX) + return WideToUTF8(SysNativeMBToWide(file_path.value())); +#else + return UTF16ToUTF8(file_path.value()); +#endif +} + +FilePath UTF8ToFilePath(const std::string& str) { + FilePath::StringType result; +#if defined(OS_POSIX) + result = SysWideToNativeMB(UTF8ToWide(str)); +#elif defined(OS_WIN) + result = UTF8ToUTF16(str); +#endif + return FilePath(result); +} + +} // namespace + +StringValue* CreateFilePathValue(const FilePath& in_value) { + return new StringValue(FilePathToUTF8(in_value)); +} + +bool GetValueAsFilePath(const Value& value, FilePath* file_path) { + std::string str; + if (!value.GetAsString(&str)) + return false; + if (file_path) + *file_path = UTF8ToFilePath(str); + return true; +} + +} // namespace base diff --git a/base/value_conversions.h b/base/value_conversions.h new file mode 100644 index 0000000..75246d1 --- /dev/null +++ b/base/value_conversions.h @@ -0,0 +1,25 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_VALUE_CONVERSIONS_H_ +#define BASE_VALUE_CONVERSIONS_H_ +#pragma once + +// This file contains methods to convert a |FilePath| to a |Value| and back. + +#include "base/base_api.h" + +class FilePath; +class StringValue; +class Value; + +namespace base { + +// The caller takes ownership of the returned value. +BASE_API StringValue* CreateFilePathValue(const FilePath& in_value); +BASE_API bool GetValueAsFilePath(const Value& value, FilePath* file_path); + +} // namespace + +#endif // BASE_VALUE_CONVERSIONS_H_ diff --git a/base/values.cc b/base/values.cc index 3340f9b..9f2816a 100644 --- a/base/values.cc +++ b/base/values.cc @@ -1,13 +1,11 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/values.h" -#include "base/file_path.h" #include "base/logging.h" #include "base/string_util.h" -#include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" namespace { @@ -97,19 +95,6 @@ StringValue* Value::CreateStringValue(const string16& in_value) { } // static -StringValue* Value::CreateFilePathValue(const FilePath& in_value) { -#if defined(OS_POSIX) - // Value::SetString only knows about UTF8 strings, so convert the path from - // the system native value to UTF8. - std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(in_value.value())); - return new StringValue(path_utf8); -#else - return new StringValue(in_value.value()); -#endif - -} - -// static BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) { return BinaryValue::Create(buffer, size); } @@ -134,10 +119,6 @@ bool Value::GetAsString(string16* out_value) const { return false; } -bool Value::GetAsFilePath(FilePath* out_value) const { - return false; -} - bool Value::GetAsList(ListValue** out_value) { return false; } @@ -269,20 +250,6 @@ bool StringValue::GetAsString(string16* out_value) const { return true; } -bool StringValue::GetAsFilePath(FilePath* out_value) const { - if (out_value) { - FilePath::StringType result; -#if defined(OS_POSIX) - // We store filepaths as UTF8, so convert it back to the system type. - result = base::SysWideToNativeMB(UTF8ToWide(value_)); -#elif defined(OS_WIN) - result = UTF8ToUTF16(value_); -#endif - *out_value = FilePath(result); - } - return true; -} - StringValue* StringValue::DeepCopy() const { return CreateStringValue(value_); } @@ -873,8 +840,10 @@ void ListValue::Append(Value* in_value) { bool ListValue::AppendIfNotPresent(Value* in_value) { DCHECK(in_value); for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) { - if ((*i)->Equals(in_value)) + if ((*i)->Equals(in_value)) { + delete in_value; return false; + } } list_.push_back(in_value); return true; diff --git a/base/values.h b/base/values.h index 5814a9f..e4949b1 100644 --- a/base/values.h +++ b/base/values.h @@ -27,13 +27,13 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/string16.h" #include "build/build_config.h" class BinaryValue; class DictionaryValue; -class FilePath; class FundamentalValue; class ListValue; class StringValue; @@ -45,7 +45,7 @@ typedef std::map<std::string, Value*> ValueMap; // The Value class is the base class for Values. A Value can be // instantiated via the Create*Value() factory methods, or by directly // creating instances of the subclasses. -class Value { +class BASE_API Value { public: enum ValueType { TYPE_NULL = 0, @@ -69,7 +69,6 @@ class Value { static FundamentalValue* CreateDoubleValue(double in_value); static StringValue* CreateStringValue(const std::string& in_value); static StringValue* CreateStringValue(const string16& in_value); - static StringValue* CreateFilePathValue(const FilePath& in_value); // This one can return NULL if the input isn't valid. If the return value // is non-null, the new object has taken ownership of the buffer pointer. @@ -94,7 +93,6 @@ class Value { virtual bool GetAsDouble(double* out_value) const; virtual bool GetAsString(std::string* out_value) const; virtual bool GetAsString(string16* out_value) const; - virtual bool GetAsFilePath(FilePath* out_value) const; virtual bool GetAsList(ListValue** out_value); // This creates a deep copy of the entire Value tree, and returns a pointer @@ -125,7 +123,7 @@ class Value { }; // FundamentalValue represents the simple fundamental types of values. -class FundamentalValue : public Value { +class BASE_API FundamentalValue : public Value { public: explicit FundamentalValue(bool in_value); explicit FundamentalValue(int in_value); @@ -149,7 +147,7 @@ class FundamentalValue : public Value { DISALLOW_COPY_AND_ASSIGN(FundamentalValue); }; -class StringValue : public Value { +class BASE_API StringValue : public Value { public: // Initializes a StringValue with a UTF-8 narrow character string. explicit StringValue(const std::string& in_value); @@ -162,7 +160,6 @@ class StringValue : public Value { // Subclassed methods virtual bool GetAsString(std::string* out_value) const; virtual bool GetAsString(string16* out_value) const; - virtual bool GetAsFilePath(FilePath* out_value) const; virtual StringValue* DeepCopy() const; virtual bool Equals(const Value* other) const; @@ -172,7 +169,7 @@ class StringValue : public Value { DISALLOW_COPY_AND_ASSIGN(StringValue); }; -class BinaryValue: public Value { +class BASE_API BinaryValue: public Value { public: virtual ~BinaryValue(); @@ -209,7 +206,7 @@ class BinaryValue: public Value { // DictionaryValue provides a key-value dictionary with (optional) "path" // parsing for recursive access; see the comment at the top of the file. Keys // are |std::string|s and should be UTF-8 encoded. -class DictionaryValue : public Value { +class BASE_API DictionaryValue : public Value { public: DictionaryValue(); virtual ~DictionaryValue(); @@ -317,7 +314,7 @@ class DictionaryValue : public Value { // YOU SHOULD ALWAYS USE THE XXXWithoutPathExpansion() APIs WITH THESE, NOT // THE NORMAL XXX() APIs. This makes sure things will work correctly if any // keys have '.'s in them. - class key_iterator + class BASE_API key_iterator : private std::iterator<std::input_iterator_tag, const std::string> { public: explicit key_iterator(ValueMap::const_iterator itr) { itr_ = itr; } @@ -347,7 +344,7 @@ class DictionaryValue : public Value { }; // This type of Value represents a list of other Value values. -class ListValue : public Value { +class BASE_API ListValue : public Value { public: typedef ValueVector::iterator iterator; typedef ValueVector::const_iterator const_iterator; @@ -402,8 +399,9 @@ class ListValue : public Value { // Appends a Value to the end of the list. void Append(Value* in_value); - // Appends a Value if it's not already present. - // Returns true if successful, or false if the value was already present. + // Appends a Value if it's not already present. Takes ownership of the + // |in_value|. Returns true if successful, or false if the value was already + // present. If the value was already present the |in_value| is deleted. bool AppendIfNotPresent(Value* in_value); // Insert a Value at index. @@ -435,7 +433,7 @@ class ListValue : public Value { // This interface is implemented by classes that know how to serialize and // deserialize Value objects. -class ValueSerializer { +class BASE_API ValueSerializer { public: virtual ~ValueSerializer(); diff --git a/base/values_unittest.cc b/base/values_unittest.cc index 5f901b5..809fe90 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc @@ -1,10 +1,10 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <limits> -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/string16.h" #include "base/utf_string_conversions.h" #include "base/values.h" diff --git a/base/version.h b/base/version.h index 28ee227..d256d06 100644 --- a/base/version.h +++ b/base/version.h @@ -9,13 +9,14 @@ #include <string> #include <vector> +#include "base/base_api.h" #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 { +class BASE_API Version { public: // Exposed only so that a Version can be stored in STL containers; // any call to the methods below on a default-constructed Version diff --git a/base/version_unittest.cc b/base/version_unittest.cc index 2e3c2ca..486ef7d 100644 --- a/base/version_unittest.cc +++ b/base/version_unittest.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/version.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/vlog.h b/base/vlog.h index 54e777f..0a55006 100644 --- a/base/vlog.h +++ b/base/vlog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,13 +10,14 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/basictypes.h" #include "base/string_piece.h" namespace logging { // A helper class containing all the settings for vlogging. -class VlogInfo { +class BASE_API VlogInfo { public: static const int kDefaultVlogLevel; @@ -70,8 +71,8 @@ class VlogInfo { // "kh*n" matches "khn", "khan", or even "khaaaaan" // "/foo\bar" matches "/foo/bar", "\foo\bar", or "/foo\bar" // (disregarding C escaping rules) -bool MatchVlogPattern(const base::StringPiece& string, - const base::StringPiece& vlog_pattern); +BASE_API bool MatchVlogPattern(const base::StringPiece& string, + const base::StringPiece& vlog_pattern); } // namespace logging diff --git a/base/win/event_trace_controller.h b/base/win/event_trace_controller.h index 8eb172e..6cc7e69 100644 --- a/base/win/event_trace_controller.h +++ b/base/win/event_trace_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -25,6 +25,8 @@ #include <wmistr.h> #include <evntrace.h> #include <string> + +#include "base/base_api.h" #include "base/basictypes.h" namespace base { @@ -33,7 +35,7 @@ namespace win { // Utility class to make it easier to work with EVENT_TRACE_PROPERTIES. // The EVENT_TRACE_PROPERTIES structure contains information about an // event tracing session. -class EtwTraceProperties { +class BASE_API EtwTraceProperties { public: EtwTraceProperties(); @@ -83,7 +85,7 @@ class EtwTraceProperties { // This class implements an ETW controller, which knows how to start and // stop event tracing sessions, as well as controlling ETW provider // log levels and enable bit masks under the session. -class EtwTraceController { +class BASE_API EtwTraceController { public: EtwTraceController(); ~EtwTraceController(); diff --git a/base/win/event_trace_provider.h b/base/win/event_trace_provider.h index 6614c91..7173025 100644 --- a/base/win/event_trace_provider.h +++ b/base/win/event_trace_provider.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -11,6 +11,8 @@ #include <windows.h> #include <wmistr.h> #include <evntrace.h> + +#include "base/base_api.h" #include "base/basictypes.h" namespace base { @@ -80,7 +82,7 @@ template <size_t N> class EtwMofEvent: public EtwMofEventBase<N> { // a particular trace level, and whether particular enable flags are set, // before other resources are consumed to generate and issue the log // messages themselves. -class EtwTraceProvider { +class BASE_API EtwTraceProvider { public: // Creates an event trace provider identified by provider_name, which // will be the name registered with Event Tracing for Windows (ETW). diff --git a/base/win/i18n.h b/base/win/i18n.h index ba0f74d..0159fd0 100644 --- a/base/win/i18n.h +++ b/base/win/i18n.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/base_api.h" #include "base/basictypes.h" namespace base { @@ -18,12 +19,14 @@ namespace i18n { // Adds to |languages| the list of user preferred UI languages from MUI, if // available, falling-back on the user default UI language otherwise. Returns // true if at least one language is added. -bool GetUserPreferredUILanguageList(std::vector<std::wstring>* languages); +BASE_API bool GetUserPreferredUILanguageList( + std::vector<std::wstring>* languages); // Adds to |languages| the list of thread, process, user, and system preferred // UI languages from MUI, if available, falling-back on the user default UI // language otherwise. Returns true if at least one language is added. -bool GetThreadPreferredUILanguageList(std::vector<std::wstring>* languages); +BASE_API bool GetThreadPreferredUILanguageList( + std::vector<std::wstring>* languages); } // namespace i18n } // namespace win diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h index 16534c2..0eef022 100644 --- a/base/win/object_watcher.h +++ b/base/win/object_watcher.h @@ -8,6 +8,7 @@ #include <windows.h> +#include "base/base_api.h" #include "base/message_loop.h" namespace base { @@ -41,7 +42,7 @@ namespace win { // scope, the watcher_ will be destroyed, and there is no need to worry about // OnObjectSignaled being called on a deleted MyClass pointer. Easy! // -class ObjectWatcher : public MessageLoop::DestructionObserver { +class BASE_API ObjectWatcher : public MessageLoop::DestructionObserver { public: class Delegate { public: diff --git a/base/win/registry.h b/base/win/registry.h index cd5421d..86785cf 100644 --- a/base/win/registry.h +++ b/base/win/registry.h @@ -9,6 +9,7 @@ #include <windows.h> #include <string> +#include "base/base_api.h" #include "base/basictypes.h" namespace base { @@ -21,7 +22,7 @@ namespace win { // Note: // ReadValue family of functions guarantee that the return arguments // are not touched in case of failure. -class RegKey { +class BASE_API RegKey { public: RegKey(); RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access); @@ -98,7 +99,7 @@ class RegKey { // For this application I happen to know I wont need data size larger // than MAX_PATH, but in real life this wouldn't neccessarily be // adequate. -class RegistryValueIterator { +class BASE_API RegistryValueIterator { public: RegistryValueIterator(HKEY root_key, const wchar_t* folder_key); @@ -138,7 +139,7 @@ class RegistryValueIterator { DISALLOW_COPY_AND_ASSIGN(RegistryValueIterator); }; -class RegistryKeyIterator { +class BASE_API RegistryKeyIterator { public: RegistryKeyIterator(HKEY root_key, const wchar_t* folder_key); diff --git a/base/win/scoped_bstr.h b/base/win/scoped_bstr.h index 944562e..61b8969 100644 --- a/base/win/scoped_bstr.h +++ b/base/win/scoped_bstr.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,6 +9,7 @@ #include <windows.h> #include <oleauto.h> +#include "base/base_api.h" #include "base/logging.h" #include "base/string16.h" @@ -17,7 +18,7 @@ namespace win { // Manages a BSTR string pointer. // The class interface is based on scoped_ptr. -class ScopedBstr { +class BASE_API ScopedBstr { public: ScopedBstr() : bstr_(NULL) { } diff --git a/base/win/scoped_comptr.h b/base/win/scoped_comptr.h index e508ef2..9a4dd9d 100644 --- a/base/win/scoped_comptr.h +++ b/base/win/scoped_comptr.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,7 @@ #include <unknwn.h> #include "base/logging.h" -#include "base/ref_counted.h" +#include "base/memory/ref_counted.h" namespace base { namespace win { diff --git a/base/win/scoped_comptr_unittest.cc b/base/win/scoped_comptr_unittest.cc index fcd0791..54dcfc0 100644 --- a/base/win/scoped_comptr_unittest.cc +++ b/base/win/scoped_comptr_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,7 @@ #include <shlobj.h> -#include "base/scoped_ptr.h" +#include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { @@ -110,4 +110,4 @@ TEST(ScopedComPtrTest, ScopedComPtrVector) { } } // namespace win -} // namespace base
\ No newline at end of file +} // namespace base diff --git a/base/win/scoped_variant.h b/base/win/scoped_variant.h index 6c4d23f..11ffa3e 100644 --- a/base/win/scoped_variant.h +++ b/base/win/scoped_variant.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,6 +9,7 @@ #include <windows.h> #include <oleauto.h> +#include "base/base_api.h" #include "base/basictypes.h" namespace base { @@ -20,7 +21,7 @@ namespace win { // Instead of inheriting from VARIANT, we take the containment approach // in order to have more control over the usage of the variant and guard // against memory leaks. -class ScopedVariant { +class BASE_API ScopedVariant { public: // Declaration of a global variant variable that's always VT_EMPTY static const VARIANT kEmptyVariant; diff --git a/base/win/win_util.cc b/base/win/win_util.cc index 76d8c5d..8a9d622 100644 --- a/base/win/win_util.cc +++ b/base/win/win_util.cc @@ -12,8 +12,8 @@ #include <shlobj.h> #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/win/registry.h" -#include "base/scoped_ptr.h" #include "base/string_util.h" #include "base/stringprintf.h" #include "base/threading/thread_restrictions.h" diff --git a/base/win/win_util.h b/base/win/win_util.h index c9bdce8..847c434 100644 --- a/base/win/win_util.h +++ b/base/win/win_util.h @@ -27,6 +27,7 @@ #include <string> +#include "base/base_api.h" #include "base/string16.h" struct IPropertyStore; @@ -36,19 +37,19 @@ typedef _tagpropertykey PROPERTYKEY; namespace base { namespace win { -void GetNonClientMetrics(NONCLIENTMETRICS* metrics); +BASE_API void GetNonClientMetrics(NONCLIENTMETRICS* metrics); // Returns the string representing the current user sid. -bool GetUserSidString(std::wstring* user_sid); +BASE_API bool GetUserSidString(std::wstring* user_sid); // Returns true if the shift key is currently pressed. -bool IsShiftPressed(); +BASE_API bool IsShiftPressed(); // Returns true if the ctrl key is currently pressed. -bool IsCtrlPressed(); +BASE_API bool IsCtrlPressed(); // Returns true if the alt key is currently pressed. -bool IsAltPressed(); +BASE_API bool IsAltPressed(); // Returns false if user account control (UAC) has been disabled with the // EnableLUA registry flag. Returns true if user account control is enabled. @@ -56,27 +57,27 @@ bool IsAltPressed(); // machines, might still exist and be set to 0 (UAC disabled), in which case // this function will return false. You should therefore check this flag only // if the OS is Vista or later. -bool UserAccountControlIsEnabled(); +BASE_API bool UserAccountControlIsEnabled(); // Sets the application id in given IPropertyStore. The function is intended // for tagging application/chromium shortcut, browser window and jump list for // Win7. -bool SetAppIdForPropertyStore(IPropertyStore* property_store, - const wchar_t* app_id); +BASE_API bool SetAppIdForPropertyStore(IPropertyStore* property_store, + const wchar_t* app_id); // Adds the specified |command| using the specified |name| to the AutoRun key. // |root_key| could be HKCU or HKLM or the root of any user hive. -bool AddCommandToAutoRun(HKEY root_key, const string16& name, - const string16& command); +BASE_API bool AddCommandToAutoRun(HKEY root_key, const string16& name, + const string16& command); // Removes the command specified by |name| from the AutoRun key. |root_key| // could be HKCU or HKLM or the root of any user hive. -bool RemoveCommandFromAutoRun(HKEY root_key, const string16& name); +BASE_API bool RemoveCommandFromAutoRun(HKEY root_key, const string16& name); // Reads the command specified by |name| from the AutoRun key. |root_key| // could be HKCU or HKLM or the root of any user hive. Used for unit-tests. -bool ReadCommandFromAutoRun(HKEY root_key, - const string16& name, - string16* command); +BASE_API bool ReadCommandFromAutoRun(HKEY root_key, + const string16& name, + string16* command); } // namespace win } // namespace base diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc index d53148d..8dc2d93 100644 --- a/base/win/windows_version.cc +++ b/base/win/windows_version.cc @@ -11,81 +11,49 @@ namespace base { namespace win { -Version GetVersion() { - static bool checked_version = false; - static Version win_version = VERSION_PRE_2000; - if (!checked_version) { - OSVERSIONINFOEX version_info; - version_info.dwOSVersionInfoSize = sizeof version_info; - GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); - if (version_info.dwMajorVersion == 5) { - switch (version_info.dwMinorVersion) { - case 0: - win_version = VERSION_2000; - break; - case 1: - win_version = VERSION_XP; - break; - case 2: - default: - win_version = VERSION_SERVER_2003; - break; - } - } else if (version_info.dwMajorVersion == 6) { - if (version_info.wProductType != VER_NT_WORKSTATION) { - // 2008 is 6.0, and 2008 R2 is 6.1. - win_version = VERSION_2008; - } else { - if (version_info.dwMinorVersion == 0) { - win_version = VERSION_VISTA; - } else { - win_version = VERSION_WIN7; - } - } - } else if (version_info.dwMajorVersion > 6) { - win_version = VERSION_WIN7; - } - checked_version = true; - } - return win_version; +// static +OSInfo* OSInfo::GetInstance() { + return Singleton<OSInfo>::get(); } -void GetServicePackLevel(int* major, int* minor) { - DCHECK(major && minor); - static bool checked_version = false; - static int service_pack_major = -1; - static int service_pack_minor = -1; - if (!checked_version) { - OSVERSIONINFOEX version_info = {0}; - version_info.dwOSVersionInfoSize = sizeof(version_info); - GetVersionEx(reinterpret_cast<OSVERSIONINFOW*>(&version_info)); - service_pack_major = version_info.wServicePackMajor; - service_pack_minor = version_info.wServicePackMinor; - checked_version = true; +OSInfo::OSInfo() + : version_(VERSION_PRE_XP), + architecture_(OTHER_ARCHITECTURE), + wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) { + OSVERSIONINFOEX version_info = { sizeof version_info }; + GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); + version_number_.major = version_info.dwMajorVersion; + version_number_.minor = version_info.dwMinorVersion; + version_number_.build = version_info.dwBuildNumber; + if ((version_number_.major == 5) && (version_number_.minor > 0)) { + version_ = (version_number_.minor == 1) ? VERSION_XP : VERSION_SERVER_2003; + } else if (version_number_.major == 6) { + if (version_info.wProductType == VER_NT_WORKSTATION) + version_ = (version_number_.minor == 0) ? VERSION_VISTA : VERSION_WIN7; + else + version_ = VERSION_SERVER_2008; + } else if (version_number_.major > 6) { + version_ = VERSION_WIN7; } + service_pack_.major = version_info.wServicePackMajor; + service_pack_.minor = version_info.wServicePackMinor; - *major = service_pack_major; - *minor = service_pack_minor; -} - -WindowsArchitecture GetWindowsArchitecture() { - SYSTEM_INFO system_info; + SYSTEM_INFO system_info = { 0 }; GetNativeSystemInfo(&system_info); switch (system_info.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_INTEL: return X86_ARCHITECTURE; - case PROCESSOR_ARCHITECTURE_AMD64: return X64_ARCHITECTURE; - case PROCESSOR_ARCHITECTURE_IA64: return IA64_ARCHITECTURE; - default: return OTHER_ARCHITECTURE; + case PROCESSOR_ARCHITECTURE_INTEL: architecture_ = X86_ARCHITECTURE; break; + case PROCESSOR_ARCHITECTURE_AMD64: architecture_ = X64_ARCHITECTURE; break; + case PROCESSOR_ARCHITECTURE_IA64: architecture_ = IA64_ARCHITECTURE; break; } + processors_ = system_info.dwNumberOfProcessors; + allocation_granularity_ = system_info.dwAllocationGranularity; } -WOW64Status GetWOW64Status() { - static WOW64Status wow64_status = - GetWOW64StatusForProcess(GetCurrentProcess()); - return wow64_status; +OSInfo::~OSInfo() { } -WOW64Status GetWOW64StatusForProcess(HANDLE process_handle) { +// static +OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) { typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL); IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>( GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process")); @@ -97,5 +65,9 @@ WOW64Status GetWOW64StatusForProcess(HANDLE process_handle) { return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED; } +Version GetVersion() { + return OSInfo::GetInstance()->version(); +} + } // namespace win } // namespace base diff --git a/base/win/windows_version.h b/base/win/windows_version.h index df3cc35..96f3792 100644 --- a/base/win/windows_version.h +++ b/base/win/windows_version.h @@ -6,60 +6,99 @@ #define BASE_WIN_WINDOWS_VERSION_H_ #pragma once +#include "base/base_api.h" +#include "base/memory/singleton.h" + typedef void* HANDLE; namespace base { namespace win { +// The running version of Windows. This is declared outside OSInfo for +// syntactic sugar reasons; see the declaration of GetVersion() below. // NOTE: Keep these in order so callers can do things like -// "if (GetWinVersion() > WINVERSION_2000) ...". It's OK to change the values, -// though. +// "if (base::win::GetVersion() >= base::win::VERSION_VISTA) ...". enum Version { - VERSION_PRE_2000 = 0, // Not supported - VERSION_2000 = 1, // Not supported - VERSION_XP = 2, - VERSION_SERVER_2003 = 3, // Also includes Windows XP Professional x64 edition - VERSION_VISTA = 4, - VERSION_2008 = 5, - VERSION_WIN7 = 6, + VERSION_PRE_XP = 0, // Not supported. + VERSION_XP, + VERSION_SERVER_2003, // Also includes Windows XP Professional x64. + VERSION_VISTA, + VERSION_SERVER_2008, + VERSION_WIN7, }; -// Returns the running version of Windows. -Version GetVersion(); +// A Singleton that can be used to query various pieces of information about the +// OS and process state. +class BASE_API OSInfo { + public: + struct VersionNumber { + int major; + int minor; + int build; + }; -// Returns the major and minor version of the service pack installed. -void GetServicePackLevel(int* major, int* minor); + struct ServicePack { + int major; + int minor; + }; -enum WindowsArchitecture { - X86_ARCHITECTURE, - X64_ARCHITECTURE, - IA64_ARCHITECTURE, - OTHER_ARCHITECTURE, -}; + // The processor architecture this copy of Windows natively uses. For + // example, given an x64-capable processor, we have three possibilities: + // 32-bit Chrome running on 32-bit Windows: X86_ARCHITECTURE + // 32-bit Chrome running on 64-bit Windows via WOW64: X64_ARCHITECTURE + // 64-bit Chrome running on 64-bit Windows: X64_ARCHITECTURE + enum WindowsArchitecture { + X86_ARCHITECTURE, + X64_ARCHITECTURE, + IA64_ARCHITECTURE, + OTHER_ARCHITECTURE, + }; -// Returns the processor architecture this copy of Windows natively uses. -// For example, given an x64-capable processor, we have three possibilities: -// 32-bit Chrome running on 32-bit Windows: X86_ARCHITECTURE -// 32-bit Chrome running on 64-bit Windows via WOW64: X64_ARCHITECTURE -// 64-bit Chrome running on 64-bit Windows: X64_ARCHITECTURE -WindowsArchitecture GetWindowsArchitecture(); - -enum WOW64Status { - WOW64_DISABLED, - WOW64_ENABLED, - WOW64_UNKNOWN, -}; + // Whether a process is running under WOW64 (the wrapper that allows 32-bit + // processes to run on 64-bit versions of Windows). This will return + // WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit + // Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. + // the process does not have sufficient access rights to determine this. + enum WOW64Status { + WOW64_DISABLED, + WOW64_ENABLED, + WOW64_UNKNOWN, + }; + + static OSInfo* GetInstance(); + + Version version() const { return version_; } + // The next two functions return arrays of values, [major, minor(, build)]. + VersionNumber version_number() const { return version_number_; } + ServicePack service_pack() const { return service_pack_; } + WindowsArchitecture architecture() const { return architecture_; } + int processors() const { return processors_; } + size_t allocation_granularity() const { return allocation_granularity_; } + WOW64Status wow64_status() const { return wow64_status_; } -// Returns whether this process is running under WOW64 (the wrapper that allows -// 32-bit processes to run on 64-bit versions of Windows). This will return -// WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit Chrome -// on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. the -// process does not have sufficient access rights to determine this. -WOW64Status GetWOW64Status(); + // Like wow64_status(), but for the supplied handle instead of the current + // process. This doesn't touch member state, so you can bypass the singleton. + static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); + + private: + OSInfo(); + ~OSInfo(); + + Version version_; + VersionNumber version_number_; + ServicePack service_pack_; + WindowsArchitecture architecture_; + int processors_; + size_t allocation_granularity_; + WOW64Status wow64_status_; + + friend struct DefaultSingletonTraits<OSInfo>; + DISALLOW_COPY_AND_ASSIGN(OSInfo); +}; -// Like GetWOW64Status(), but for the supplied handle instead of the current -// process. -WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); +// Because this is by far the most commonly-requested value from the above +// singleton, we add a global-scope accessor here as syntactic sugar. +BASE_API Version GetVersion(); } // namespace win } // namespace base diff --git a/base/win/wrapped_window_proc.cc b/base/win/wrapped_window_proc.cc new file mode 100644 index 0000000..c94c5ae --- /dev/null +++ b/base/win/wrapped_window_proc.cc @@ -0,0 +1,32 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/win/wrapped_window_proc.h" + +#include "base/atomicops.h" + +namespace { + +base::win::WinProcExceptionFilter s_exception_filter = NULL; + +} // namespace. + +namespace base { +namespace win { + +WinProcExceptionFilter SetWinProcExceptionFilter( + WinProcExceptionFilter filter) { + subtle::AtomicWord rv = subtle::NoBarrier_AtomicExchange( + reinterpret_cast<subtle::AtomicWord*>(&s_exception_filter), + reinterpret_cast<subtle::AtomicWord>(filter)); + return reinterpret_cast<WinProcExceptionFilter>(rv); +} + +int CallExceptionFilter(EXCEPTION_POINTERS* info) { + return s_exception_filter ? s_exception_filter(info) : + EXCEPTION_CONTINUE_SEARCH; +} + +} // namespace win +} // namespace base diff --git a/base/win/wrapped_window_proc.h b/base/win/wrapped_window_proc.h new file mode 100644 index 0000000..eac150e --- /dev/null +++ b/base/win/wrapped_window_proc.h @@ -0,0 +1,69 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Provides a way to handle exceptions that happen while a WindowProc is +// running. The behavior of exceptions generated inside a WindowProc is OS +// dependent, but it is possible that the OS just ignores the exception and +// continues execution, which leads to unpredictable behavior for Chrome. + +#ifndef BASE_WIN_WRAPPED_WINDOW_PROC_H_ +#define BASE_WIN_WRAPPED_WINDOW_PROC_H_ +#pragma once + +#include <windows.h> + +#include "base/base_api.h" + +namespace base { +namespace win { + +// An exception filter for a WindowProc. The return value determines how the +// exception should be handled, following standard SEH rules. However, the +// expected behavior for this function is to not return, instead of returning +// EXCEPTION_EXECUTE_HANDLER or similar, given that in general we are not +// prepared to handle exceptions. +typedef int (__cdecl *WinProcExceptionFilter)(EXCEPTION_POINTERS* info); + +// Sets the filter to deal with exceptions inside a WindowProc. Returns the old +// exception filter, if any. +// This function should be called before any window is created. +BASE_API WinProcExceptionFilter SetWinProcExceptionFilter( + WinProcExceptionFilter filter); + +// Calls the registered exception filter. +BASE_API int CallExceptionFilter(EXCEPTION_POINTERS* info); + +// Wrapper that supplies a standard exception frame for the provided WindowProc. +// The normal usage is something like this: +// +// LRESULT CALLBACK MyWinProc(HWND hwnd, UINT message, +// WPARAM wparam, LPARAM lparam) { +// // Do Something. +// } +// +// ... +// +// WNDCLASSEX wc = {0}; +// wc.lpfnWndProc = WrappedWindowProc<MyWinProc>; +// wc.lpszClassName = class_name; +// ... +// RegisterClassEx(&wc); +// +// CreateWindowW(class_name, window_name, ... +// +template <WNDPROC proc> +LRESULT CALLBACK WrappedWindowProc(HWND hwnd, UINT message, + WPARAM wparam, LPARAM lparam) { + LRESULT rv = 0; + __try { + rv = proc(hwnd, message, wparam, lparam); + } __except(CallExceptionFilter(GetExceptionInformation())) { + } + return rv; +} + +} // namespace win +} // namespace base + +#endif // BASE_WIN_WRAPPED_WINDOW_PROC_H_ diff --git a/base/win/wrapped_window_proc_unittest.cc b/base/win/wrapped_window_proc_unittest.cc new file mode 100644 index 0000000..ccf3c85 --- /dev/null +++ b/base/win/wrapped_window_proc_unittest.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/win/wrapped_window_proc.h" +#include "base/message_loop.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +DWORD kExceptionCode = 12345; +WPARAM kCrashMsg = 98765; + +// A trivial WindowProc that generates an exception. +LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT message, + WPARAM wparam, LPARAM lparam) { + if (message == kCrashMsg) + RaiseException(kExceptionCode, 0, 0, NULL); + return DefWindowProc(hwnd, message, wparam, lparam); +} + +// This class implements an exception filter that can be queried about a past +// exception. +class TestWrappedExceptionFiter { + public: + TestWrappedExceptionFiter() : called_(false) { + EXPECT_FALSE(s_filter_); + s_filter_ = this; + } + + ~TestWrappedExceptionFiter() { + EXPECT_EQ(s_filter_, this); + s_filter_ = NULL; + } + + bool called() { + return called_; + } + + // The actual exception filter just records the exception. + static int Filter(EXCEPTION_POINTERS* info) { + EXPECT_FALSE(s_filter_->called_); + if (info->ExceptionRecord->ExceptionCode == kExceptionCode) + s_filter_->called_ = true; + return EXCEPTION_EXECUTE_HANDLER; + } + + private: + bool called_; + static TestWrappedExceptionFiter* s_filter_; +}; +TestWrappedExceptionFiter* TestWrappedExceptionFiter::s_filter_ = NULL; + +} // namespace. + +TEST(WrappedWindowProc, CatchesExceptions) { + HINSTANCE hinst = GetModuleHandle(NULL); + std::wstring class_name(L"TestClass"); + + WNDCLASS wc = {0}; + wc.lpfnWndProc = base::win::WrappedWindowProc<TestWindowProc>; + wc.hInstance = hinst; + wc.lpszClassName = class_name.c_str(); + RegisterClass(&wc); + + HWND window = CreateWindow(class_name.c_str(), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, + 0, hinst, 0); + ASSERT_TRUE(window); + + // Before generating the exception we make sure that the filter will see it. + TestWrappedExceptionFiter wrapper; + base::win::WinProcExceptionFilter old_filter = + base::win::SetWinProcExceptionFilter(TestWrappedExceptionFiter::Filter); + + SendMessage(window, kCrashMsg, 0, 0); + EXPECT_TRUE(wrapper.called()); + + base::win::SetWinProcExceptionFilter(old_filter); +} |