Initialize Tizen 2.3 2.3a_release submit/tizen_2.3/20140531.063551
authorSehong Na <sehong.na@samsung.com>
Sat, 31 May 2014 03:34:24 +0000 (12:34 +0900)
committerSehong Na <sehong.na@samsung.com>
Sat, 31 May 2014 03:34:24 +0000 (12:34 +0900)
105 files changed:
.merge_20130204.054301 [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0755]
LICENSE [new file with mode: 0755]
NOTICE [new file with mode: 0644]
base/OWNERS [new file with mode: 0644]
base/atomic_ref_count.h [new file with mode: 0644]
base/atomic_sequence_num.h [new file with mode: 0644]
base/atomicops.h [new file with mode: 0644]
base/atomicops_internals_arm_gcc.h [new file with mode: 0644]
base/atomicops_internals_atomicword_compat.h [new file with mode: 0644]
base/atomicops_internals_x86_gcc.cc [new file with mode: 0644]
base/atomicops_internals_x86_gcc.h [new file with mode: 0644]
base/atomicops_internals_x86_macosx.h [new file with mode: 0644]
base/atomicops_internals_x86_msvc.h [new file with mode: 0644]
base/base_export.h [new file with mode: 0644]
base/basictypes.h [new file with mode: 0644]
base/compiler_specific.h [new file with mode: 0644]
base/file_descriptor_posix.h [new file with mode: 0644]
base/hash_tables.h [new file with mode: 0644]
base/logging.h [new file with mode: 0644]
base/memory/ref_counted.cc [new file with mode: 0644]
base/memory/ref_counted.h [new file with mode: 0644]
base/memory/ref_counted_memory.cc [new file with mode: 0644]
base/memory/ref_counted_memory.h [new file with mode: 0644]
base/memory/ref_counted_memory_unittest.cc [new file with mode: 0644]
base/memory/ref_counted_unittest.cc [new file with mode: 0644]
base/pickle.cc [new file with mode: 0644]
base/pickle.h [new file with mode: 0644]
base/platform_file_posix.cc [new file with mode: 0644]
base/port.h [new file with mode: 0644]
base/string16.cc [new file with mode: 0644]
base/string16.h [new file with mode: 0644]
base/string_number_conversions.cc [new file with mode: 0644]
base/string_number_conversions.h [new file with mode: 0644]
base/string_piece.cc [new file with mode: 0644]
base/string_piece.h [new file with mode: 0644]
base/synchronization/lock.h [new file with mode: 0644]
base/synchronization/lock_impl.h [new file with mode: 0644]
base/synchronization/waitable_event.h [new file with mode: 0644]
base/template_util.h [new file with mode: 0644]
base/third_party/dynamic_annotations/LICENSE [new file with mode: 0644]
base/third_party/dynamic_annotations/README.chromium [new file with mode: 0644]
base/third_party/dynamic_annotations/dynamic_annotations.c [new file with mode: 0644]
base/third_party/dynamic_annotations/dynamic_annotations.gyp [new file with mode: 0644]
base/third_party/dynamic_annotations/dynamic_annotations.h [new file with mode: 0644]
base/threading/platform_thread.h [new file with mode: 0644]
base/threading/platform_thread_posix.cc [new file with mode: 0644]
base/threading/thread.cc [new file with mode: 0644]
base/threading/thread.h [new file with mode: 0644]
base/threading/thread_collision_warner.cc [new file with mode: 0644]
base/threading/thread_collision_warner.h [new file with mode: 0644]
base/time.h [new file with mode: 0644]
base/tuple.h [new file with mode: 0644]
base/values.cc [new file with mode: 0644]
base/values.h [new file with mode: 0644]
build/build_config.h [new file with mode: 0644]
chromium.manifest [new file with mode: 0644]
chromium.pc.in [new file with mode: 0755]
ipc/OWNERS [new file with mode: 0644]
ipc/file_descriptor_set_posix.cc [new file with mode: 0644]
ipc/file_descriptor_set_posix.h [new file with mode: 0644]
ipc/file_descriptor_set_posix_unittest.cc [new file with mode: 0644]
ipc/ipc.gyp [new file with mode: 0644]
ipc/ipc.gypi [new file with mode: 0644]
ipc/ipc_channel.h [new file with mode: 0644]
ipc/ipc_channel_handle.h [new file with mode: 0644]
ipc/ipc_channel_posix.cc [new file with mode: 0644]
ipc/ipc_channel_posix.h [new file with mode: 0644]
ipc/ipc_channel_posix_unittest.cc [new file with mode: 0644]
ipc/ipc_channel_proxy.cc [new file with mode: 0644]
ipc/ipc_channel_proxy.h [new file with mode: 0644]
ipc/ipc_channel_win.cc [new file with mode: 0644]
ipc/ipc_channel_win.h [new file with mode: 0644]
ipc/ipc_descriptors.h [new file with mode: 0644]
ipc/ipc_export.h [new file with mode: 0644]
ipc/ipc_logging.cc [new file with mode: 0644]
ipc/ipc_logging.h [new file with mode: 0644]
ipc/ipc_message.cc [new file with mode: 0644]
ipc/ipc_message.h [new file with mode: 0644]
ipc/ipc_message_macros.h [new file with mode: 0644]
ipc/ipc_message_null_macros.h [new file with mode: 0644]
ipc/ipc_message_utils.cc [new file with mode: 0644]
ipc/ipc_message_utils.h [new file with mode: 0755]
ipc/ipc_message_utils_impl.h [new file with mode: 0644]
ipc/ipc_param_traits.h [new file with mode: 0644]
ipc/ipc_platform_file.cc [new file with mode: 0644]
ipc/ipc_platform_file.h [new file with mode: 0644]
ipc/ipc_switches.cc [new file with mode: 0644]
ipc/ipc_switches.h [new file with mode: 0644]
ipc/ipc_sync_channel.cc [new file with mode: 0644]
ipc/ipc_sync_channel.h [new file with mode: 0644]
ipc/ipc_sync_message.cc [new file with mode: 0644]
ipc/ipc_sync_message.h [new file with mode: 0644]
ipc/ipc_sync_message_filter.cc [new file with mode: 0644]
ipc/ipc_sync_message_filter.h [new file with mode: 0644]
ipc/param_traits_log_macros.h [new file with mode: 0644]
ipc/param_traits_macros.h [new file with mode: 0644]
ipc/param_traits_read_macros.h [new file with mode: 0644]
ipc/param_traits_write_macros.h [new file with mode: 0644]
ipc/struct_constructor_macros.h [new file with mode: 0644]
ipc/struct_destructor_macros.h [new file with mode: 0644]
ipc/sync_socket_unittest.cc [new file with mode: 0644]
log.h [new file with mode: 0644]
packaging/chromium.changes [new file with mode: 0644]
packaging/chromium.spec [new file with mode: 0755]

diff --git a/.merge_20130204.054301 b/.merge_20130204.054301
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..a02ca6c
--- /dev/null
@@ -0,0 +1,77 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+PROJECT(chromium)
+
+SET(CMAKE_INSTALL_PREFIX /usr)
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+
+SET(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/cmake_build_tmp/output)
+set(MODULE_DIR ${CMAKE_SOURCE_DIR})
+
+SET (${PROJECT_NAME}_SOURCE_FILES
+       ${MODULE_DIR}/base/pickle.cc
+       ${MODULE_DIR}/ipc/ipc_message.cc
+       ${MODULE_DIR}/ipc/ipc_message_utils.cc
+       ${MODULE_DIR}/ipc/ipc_sync_message.cc
+       )
+
+LIST (APPEND SRCS ${${PROJECT_NAME}_SOURCE_FILES})
+
+INCLUDE_DIRECTORIES(
+       ${MODULE_DIR}
+) 
+
+add_library(${PROJECT_NAME} SHARED ${SRCS})
+
+#FIND_LIBRARY(MYAPILIB NAMES pthread PATHS /usr/lib) 
+
+SET(CMAKE_C_FLAGS "${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}")
+SET(CMAKE_CXX_FLAGS "${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}")
+
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} 
+       PROPERTIES 
+       VERSION ${FULLVER}
+       SOVERSION ${MAJORVER}
+       CLEAN_DIRECT_OUTPUT 1
+       )
+
+SET(PC_NAME ${PROJECT_NAME})
+SET(PC_REQUIRED ${pc_requires})
+SET(PC_LDFLAGS -l${PROJECT_NAME})
+
+CONFIGURE_FILE(
+    chromium.pc.in
+    ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.pc
+    @ONLY
+)
+
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig)
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib${LIB_SUFFIX})
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/log.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/atomic_ref_count.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/atomicops.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/atomicops_internals_arm_gcc.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/atomicops_internals_atomicword_compat.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/atomicops_internals_x86_gcc.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/atomicops_internals_x86_macosx.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/atomicops_internals_x86_msvc.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/basictypes.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/base_export.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/compiler_specific.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/file_descriptor_posix.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/memory/ref_counted.h DESTINATION include/${PROJECT_NAME}/base/memory)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/third_party/dynamic_annotations/dynamic_annotations.h DESTINATION include/${PROJECT_NAME}/base/third_party/dynamic_annotations)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/threading/thread_collision_warner.h DESTINATION include/${PROJECT_NAME}/base/threading)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/hash_tables.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/logging.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/pickle.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/port.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/string16.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/string_number_conversions.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/string_piece.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/time.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/tuple.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/base/values.h DESTINATION include/${PROJECT_NAME}/base)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/build/build_config.h DESTINATION include/${PROJECT_NAME}/build)
+INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/ipc/ DESTINATION include/${PROJECT_NAME}/ipc FILES_MATCHING PATTERN "*.h")
diff --git a/LICENSE b/LICENSE
new file mode 100755 (executable)
index 0000000..2fe19f6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are\r
+// met:\r
+//\r
+//    * Redistributions of source code must retain the above copyright\r
+// notice, this list of conditions and the following disclaimer.\r
+//    * Redistributions in binary form must reproduce the above\r
+// copyright notice, this list of conditions and the following disclaimer\r
+// in the documentation and/or other materials provided with the\r
+// distribution.\r
+//    * Neither the name of Google Inc. nor the names of its\r
+// contributors may be used to endorse or promote products derived from\r
+// this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..5f4a4c5
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) 2011 The Chromium Authors. All rights reserved.
+This software is excerpted from the Chromium project.
+Please, see the LICENSE file for licenses.
diff --git a/base/OWNERS b/base/OWNERS
new file mode 100644 (file)
index 0000000..41dd3c9
--- /dev/null
@@ -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/atomic_ref_count.h b/base/atomic_ref_count.h
new file mode 100644 (file)
index 0000000..985c42c
--- /dev/null
@@ -0,0 +1,81 @@
+// 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/memory/ref_counted.h directly instead.
+//
+// The implementation includes annotations to avoid some false positives
+// when using data race detection tools.
+
+#ifndef BASE_ATOMIC_REF_COUNT_H_
+#define BASE_ATOMIC_REF_COUNT_H_
+#pragma once
+
+#include "base/atomicops.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+
+namespace base {
+
+typedef subtle::Atomic32 AtomicRefCount;
+
+// Increment a reference count by "increment", which must exceed 0.
+inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
+                               AtomicRefCount increment) {
+  subtle::NoBarrier_AtomicIncrement(ptr, increment);
+}
+
+// Decrement a reference count by "decrement", which must exceed 0,
+// and return whether the result is non-zero.
+// Insert barriers to ensure that state written before the reference count
+// became zero will be visible to a thread that has just made the count zero.
+inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
+                               AtomicRefCount decrement) {
+  ANNOTATE_HAPPENS_BEFORE(ptr);
+  bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
+  if (!res) {
+    ANNOTATE_HAPPENS_AFTER(ptr);
+  }
+  return res;
+}
+
+// Increment a reference count by 1.
+inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
+  base::AtomicRefCountIncN(ptr, 1);
+}
+
+// Decrement a reference count by 1 and return whether the result is non-zero.
+// Insert barriers to ensure that state written before the reference count
+// became zero will be visible to a thread that has just made the count zero.
+inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) {
+  return base::AtomicRefCountDecN(ptr, 1);
+}
+
+// Return whether the reference count is one.  If the reference count is used
+// in the conventional way, a refrerence count of 1 implies that the current
+// thread owns the reference and no other thread shares it.  This call performs
+// the test for a reference count of one, and performs the memory barrier
+// needed for the owning thread to act on the object, knowing that it has
+// exclusive access to the object.
+inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
+  bool res = (subtle::Acquire_Load(ptr) == 1);
+  if (res) {
+    ANNOTATE_HAPPENS_AFTER(ptr);
+  }
+  return res;
+}
+
+// Return whether the reference count is zero.  With conventional object
+// referencing counting, the object will be destroyed, so the reference count
+// should never be zero.  Hence this is generally used for a debug check.
+inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
+  bool res = (subtle::Acquire_Load(ptr) == 0);
+  if (res) {
+    ANNOTATE_HAPPENS_AFTER(ptr);
+  }
+  return res;
+}
+
+}  // namespace base
+
+#endif  // BASE_ATOMIC_REF_COUNT_H_
diff --git a/base/atomic_sequence_num.h b/base/atomic_sequence_num.h
new file mode 100644 (file)
index 0000000..11805a0
--- /dev/null
@@ -0,0 +1,31 @@
+// 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_ATOMIC_SEQUENCE_NUM_H_
+#define BASE_ATOMIC_SEQUENCE_NUM_H_
+#pragma once
+
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+
+namespace base {
+
+class AtomicSequenceNumber {
+ public:
+  AtomicSequenceNumber() : seq_(0) { }
+  explicit AtomicSequenceNumber(base::LinkerInitialized x) { /* seq_ is 0 */ }
+
+  int GetNext() {
+    return static_cast<int>(
+        base::subtle::NoBarrier_AtomicIncrement(&seq_, 1) - 1);
+  }
+
+ private:
+  base::subtle::Atomic32 seq_;
+  DISALLOW_COPY_AND_ASSIGN(AtomicSequenceNumber);
+};
+
+}  // namespace base
+
+#endif  // BASE_ATOMIC_SEQUENCE_NUM_H_
diff --git a/base/atomicops.h b/base/atomicops.h
new file mode 100644 (file)
index 0000000..a087e3d
--- /dev/null
@@ -0,0 +1,150 @@
+// 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.
+
+// For atomic operations on reference counts, see atomic_refcount.h.
+// For atomic operations on sequence numbers, see atomic_sequence_num.h.
+
+// The routines exported by this module are subtle.  If you use them, even if
+// you get the code right, it will depend on careful reasoning about atomicity
+// and memory ordering; it will be less readable, and harder to maintain.  If
+// you plan to use these routines, you should have a good reason, such as solid
+// evidence that performance would otherwise suffer, or there being no
+// alternative.  You should assume only properties explicitly guaranteed by the
+// specifications in this file.  You are almost certainly _not_ writing code
+// just for the x86; if you assume x86 semantics, x86 hardware bugs and
+// implementations on other archtectures will cause your code to break.  If you
+// do not know what you are doing, avoid these routines, and use a Mutex.
+//
+// It is incorrect to make direct assignments to/from an atomic variable.
+// You should use one of the Load or Store routines.  The NoBarrier
+// versions are provided when no barriers are needed:
+//   NoBarrier_Store()
+//   NoBarrier_Load()
+// Although there are currently no compiler enforcement, you are encouraged
+// to use these.
+//
+
+#ifndef BASE_ATOMICOPS_H_
+#define BASE_ATOMICOPS_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+
+namespace base {
+namespace subtle {
+
+typedef int32 Atomic32;
+#ifdef ARCH_CPU_64_BITS
+// We need to be able to go between Atomic64 and AtomicWord implicitly.  This
+// means Atomic64 and AtomicWord should be the same type on 64-bit.
+#if defined(OS_NACL)
+// NaCl's intptr_t is not actually 64-bits on 64-bit!
+// http://code.google.com/p/nativeclient/issues/detail?id=1162
+typedef int64_t Atomic64;
+#else
+typedef intptr_t Atomic64;
+#endif
+#endif
+
+// Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
+// Atomic64 routines below, depending on your architecture.
+typedef intptr_t AtomicWord;
+
+// Atomically execute:
+//      result = *ptr;
+//      if (*ptr == old_value)
+//        *ptr = new_value;
+//      return result;
+//
+// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
+// Always return the old value of "*ptr"
+//
+// This routine implies no memory barriers.
+Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                  Atomic32 old_value,
+                                  Atomic32 new_value);
+
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
+
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
+
+Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                 Atomic32 increment);
+
+// These following lower-level operations are typically useful only to people
+// implementing higher-level synchronization operations like spinlocks,
+// mutexes, and condition-variables.  They combine CompareAndSwap(), a load, or
+// a store with appropriate memory-ordering instructions.  "Acquire" operations
+// ensure that no later memory access can be reordered ahead of the operation.
+// "Release" operations ensure that no previous memory access can be reordered
+// after the operation.  "Barrier" operations have both "Acquire" and "Release"
+// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
+// access.
+Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value);
+Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value);
+
+void MemoryBarrier();
+void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
+void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
+void Release_Store(volatile Atomic32* ptr, Atomic32 value);
+
+Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
+Atomic32 Acquire_Load(volatile const Atomic32* ptr);
+Atomic32 Release_Load(volatile const Atomic32* ptr);
+
+// 64-bit atomic operations (only available on 64-bit processors).
+#ifdef ARCH_CPU_64_BITS
+Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                  Atomic64 old_value,
+                                  Atomic64 new_value);
+Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
+Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+
+Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                Atomic64 old_value,
+                                Atomic64 new_value);
+Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                Atomic64 old_value,
+                                Atomic64 new_value);
+void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
+void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
+void Release_Store(volatile Atomic64* ptr, Atomic64 value);
+Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
+Atomic64 Acquire_Load(volatile const Atomic64* ptr);
+Atomic64 Release_Load(volatile const Atomic64* ptr);
+#endif  // ARCH_CPU_64_BITS
+
+}  // namespace base::subtle
+}  // namespace base
+
+// Include our platform specific implementation.
+#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
+#include "base/atomicops_internals_x86_msvc.h"
+#elif defined(OS_MACOSX) && defined(ARCH_CPU_X86_FAMILY)
+#include "base/atomicops_internals_x86_macosx.h"
+#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
+#include "base/atomicops_internals_x86_gcc.h"
+#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)
+#include "base/atomicops_internals_arm_gcc.h"
+#else
+#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_arm_gcc.h b/base/atomicops_internals_arm_gcc.h
new file mode 100644 (file)
index 0000000..091b34d
--- /dev/null
@@ -0,0 +1,125 @@
+// 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.
+
+// This file is an internal atomic implementation, use base/atomicops.h instead.
+//
+// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
+#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
+#pragma once
+
+namespace base {
+namespace subtle {
+
+// 0xffff0fc0 is the hard coded address of a function provided by
+// the kernel which implements an atomic compare-exchange. On older
+// ARM architecture revisions (pre-v6) this may be implemented using
+// a syscall. This address is stable, and in active use (hard coded)
+// by at least glibc-2.7 and the Android C library.
+typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
+                                           Atomic32 new_value,
+                                           volatile Atomic32* ptr);
+LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
+    (LinuxKernelCmpxchgFunc) 0xffff0fc0;
+
+typedef void (*LinuxKernelMemoryBarrierFunc)(void);
+LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
+    (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
+
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value = *ptr;
+  do {
+    if (!pLinuxKernelCmpxchg(old_value, new_value,
+                             const_cast<Atomic32*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  do {
+    old_value = *ptr;
+  } while (pLinuxKernelCmpxchg(old_value, new_value,
+                               const_cast<Atomic32*>(ptr)));
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  for (;;) {
+    // Atomic exchange the old value with an incremented one.
+    Atomic32 old_value = *ptr;
+    Atomic32 new_value = old_value + increment;
+    if (pLinuxKernelCmpxchg(old_value, new_value,
+                            const_cast<Atomic32*>(ptr)) == 0) {
+      // The exchange took place as expected.
+      return new_value;
+    }
+    // Otherwise, *ptr changed mid-loop and we need to retry.
+  }
+
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() {
+  pLinuxKernelMemoryBarrier();
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+} // namespace base::subtle
+} // namespace base
+
+#endif  // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
diff --git a/base/atomicops_internals_atomicword_compat.h b/base/atomicops_internals_atomicword_compat.h
new file mode 100644 (file)
index 0000000..8382fe1
--- /dev/null
@@ -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_gcc.cc b/base/atomicops_internals_x86_gcc.cc
new file mode 100644 (file)
index 0000000..933ca51
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This module gets enough CPU information to optimize the
+// atomicops module on x86.
+
+#include <string.h>
+
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+
+// This file only makes sense with atomicops_internals_x86_gcc.h -- it
+// depends on structs that are defined in that file.  If atomicops.h
+// doesn't sub-include that file, then we aren't needed, and shouldn't
+// try to do anything.
+#ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
+
+// Inline cpuid instruction.  In PIC compilations, %ebx contains the address
+// of the global offset table.  To avoid breaking such executables, this code
+// must preserve that register's value across cpuid instructions.
+#if defined(__i386__)
+#define cpuid(a, b, c, d, inp) \
+  asm ("mov %%ebx, %%edi\n"    \
+       "cpuid\n"               \
+       "xchg %%edi, %%ebx\n"   \
+       : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
+#elif defined (__x86_64__)
+#define cpuid(a, b, c, d, inp) \
+  asm ("mov %%rbx, %%rdi\n"    \
+       "cpuid\n"               \
+       "xchg %%rdi, %%rbx\n"   \
+       : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
+#endif
+
+#if defined(cpuid)        // initialize the struct only on x86
+
+// Set the flags so that code will run correctly and conservatively, so even
+// if we haven't been initialized yet, we're probably single threaded, and our
+// default values should hopefully be pretty safe.
+struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
+  false,          // bug can't exist before process spawns multiple threads
+  false,          // no SSE2
+};
+
+// Initialize the AtomicOps_Internalx86CPUFeatures struct.
+static void AtomicOps_Internalx86CPUFeaturesInit() {
+  uint32 eax;
+  uint32 ebx;
+  uint32 ecx;
+  uint32 edx;
+
+  // Get vendor string (issue CPUID with eax = 0)
+  cpuid(eax, ebx, ecx, edx, 0);
+  char vendor[13];
+  memcpy(vendor, &ebx, 4);
+  memcpy(vendor + 4, &edx, 4);
+  memcpy(vendor + 8, &ecx, 4);
+  vendor[12] = 0;
+
+  // get feature flags in ecx/edx, and family/model in eax
+  cpuid(eax, ebx, ecx, edx, 1);
+
+  int family = (eax >> 8) & 0xf;        // family and model fields
+  int model = (eax >> 4) & 0xf;
+  if (family == 0xf) {                  // use extended family and model fields
+    family += (eax >> 20) & 0xff;
+    model += ((eax >> 16) & 0xf) << 4;
+  }
+
+  // Opteron Rev E has a bug in which on very rare occasions a locked
+  // instruction doesn't act as a read-acquire barrier if followed by a
+  // non-locked read-modify-write instruction.  Rev F has this bug in
+  // pre-release versions, but not in versions released to customers,
+  // so we test only for Rev E, which is family 15, model 32..63 inclusive.
+  if (strcmp(vendor, "AuthenticAMD") == 0 &&       // AMD
+      family == 15 &&
+      32 <= model && model <= 63) {
+    AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
+  } else {
+    AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
+  }
+
+  // edx bit 26 is SSE2 which we use to tell use whether we can use mfence
+  AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1);
+}
+
+namespace {
+
+class AtomicOpsx86Initializer {
+ public:
+  AtomicOpsx86Initializer() {
+    AtomicOps_Internalx86CPUFeaturesInit();
+  }
+};
+
+// A global to get use initialized on startup via static initialization :/
+AtomicOpsx86Initializer g_initer;
+
+}  // namespace
+
+#endif  // if x86
+
+#endif  // ifdef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
diff --git a/base/atomicops_internals_x86_gcc.h b/base/atomicops_internals_x86_gcc.h
new file mode 100644 (file)
index 0000000..72fd350
--- /dev/null
@@ -0,0 +1,270 @@
+// 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_X86_GCC_H_
+#define BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
+#pragma once
+
+#include "base/base_export.h"
+
+// This struct is not part of the public API of this module; clients may not
+// use it.  (However, it's exported via BASE_EXPORT because clients implicitly
+// do use it at link time by inlining these functions.)
+// Features of this x86.  Values may not be correct before main() is run,
+// but are set conservatively.
+struct AtomicOps_x86CPUFeatureStruct {
+  bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
+                            // after acquire compare-and-swap.
+  bool has_sse2;            // Processor has SSE2.
+};
+BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct
+    AtomicOps_Internalx86CPUFeatures;
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+namespace base {
+namespace subtle {
+
+// 32-bit low-level operations on any platform.
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  __asm__ __volatile__("lock; cmpxchgl %1,%2"
+                       : "=a" (prev)
+                       : "q" (new_value), "m" (*ptr), "0" (old_value)
+                       : "memory");
+  return prev;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  __asm__ __volatile__("xchgl %1,%0"  // The lock prefix is implicit for xchg.
+                       : "=r" (new_value)
+                       : "m" (*ptr), "0" (new_value)
+                       : "memory");
+  return new_value;  // Now it's the previous value.
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 temp = increment;
+  __asm__ __volatile__("lock; xaddl %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now holds the old value of *ptr
+  return temp + increment;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  Atomic32 temp = increment;
+  __asm__ __volatile__("lock; xaddl %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now holds the old value of *ptr
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return temp + increment;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return x;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+#if defined(__x86_64__)
+
+// 64-bit implementations of memory barrier can be simpler, because it
+// "mfence" is guaranteed to exist.
+inline void MemoryBarrier() {
+  __asm__ __volatile__("mfence" : : : "memory");
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+#else
+
+inline void MemoryBarrier() {
+  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
+    __asm__ __volatile__("mfence" : : : "memory");
+  } else { // mfence is faster but not present on PIII
+    Atomic32 x = 0;
+    NoBarrier_AtomicExchange(&x, 0);  // acts as a barrier on PIII
+  }
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
+    *ptr = value;
+    __asm__ __volatile__("mfence" : : : "memory");
+  } else {
+    NoBarrier_AtomicExchange(ptr, value);
+                          // acts as a barrier on PIII
+  }
+}
+#endif
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ATOMICOPS_COMPILER_BARRIER();
+  *ptr = value; // An x86 store acts as a release barrier.
+  // See comments in Atomic64 version of Release_Store(), below.
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr; // An x86 load acts as a acquire barrier.
+  // See comments in Atomic64 version of Release_Store(), below.
+  ATOMICOPS_COMPILER_BARRIER();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#if defined(__x86_64__)
+
+// 64-bit low-level operations on 64-bit platform.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev;
+  __asm__ __volatile__("lock; cmpxchgq %1,%2"
+                       : "=a" (prev)
+                       : "q" (new_value), "m" (*ptr), "0" (old_value)
+                       : "memory");
+  return prev;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  __asm__ __volatile__("xchgq %1,%0"  // The lock prefix is implicit for xchg.
+                       : "=r" (new_value)
+                       : "m" (*ptr), "0" (new_value)
+                       : "memory");
+  return new_value;  // Now it's the previous value.
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 temp = increment;
+  __asm__ __volatile__("lock; xaddq %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now contains the previous value of *ptr
+  return temp + increment;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  Atomic64 temp = increment;
+  __asm__ __volatile__("lock; xaddq %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now contains the previous value of *ptr
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return temp + increment;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ATOMICOPS_COMPILER_BARRIER();
+
+  *ptr = value; // An x86 store acts as a release barrier
+                // for current AMD/Intel chips as of Jan 2008.
+                // See also Acquire_Load(), below.
+
+  // When new chips come out, check:
+  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+  //  System Programming Guide, Chatper 7: Multiple-processor management,
+  //  Section 7.2, Memory Ordering.
+  // Last seen at:
+  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
+  //
+  // x86 stores/loads fail to act as barriers for a few instructions (clflush
+  // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
+  // not generated by the compiler, and are rare.  Users of these instructions
+  // need to know about cache behaviour in any case since all of these involve
+  // either flushing cache lines or non-temporal cache hints.
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr; // An x86 load acts as a acquire barrier,
+                         // for current AMD/Intel chips as of Jan 2008.
+                         // See also Release_Store(), above.
+  ATOMICOPS_COMPILER_BARRIER();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return x;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+#endif  // defined(__x86_64__)
+
+} // namespace base::subtle
+} // namespace base
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
diff --git a/base/atomicops_internals_x86_macosx.h b/base/atomicops_internals_x86_macosx.h
new file mode 100644 (file)
index 0000000..4b7cec8
--- /dev/null
@@ -0,0 +1,198 @@
+// 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_X86_MACOSX_H_
+#define BASE_ATOMICOPS_INTERNALS_X86_MACOSX_H_
+#pragma once
+
+#include <libkern/OSAtomic.h>
+
+namespace base {
+namespace subtle {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap32(old_value, new_value,
+                                 const_cast<Atomic32*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  do {
+    old_value = *ptr;
+  } while (!OSAtomicCompareAndSwap32(old_value, new_value,
+                                     const_cast<Atomic32*>(ptr)));
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                          Atomic32 increment) {
+  return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                          Atomic32 increment) {
+  return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline void MemoryBarrier() {
+  OSMemoryBarrier();
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
+                                        const_cast<Atomic32*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return Acquire_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#ifdef __LP64__
+
+// 64-bit implementation on 64-bit platform
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap64(old_value, new_value,
+                                 reinterpret_cast<volatile int64_t*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
+                                         Atomic64 new_value) {
+  Atomic64 old_value;
+  do {
+    old_value = *ptr;
+  } while (!OSAtomicCompareAndSwap64(old_value, new_value,
+                                     reinterpret_cast<volatile int64_t*>(ptr)));
+  return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                          Atomic64 increment) {
+  return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                        Atomic64 increment) {
+  return OSAtomicAdd64Barrier(increment,
+                              reinterpret_cast<volatile int64_t*>(ptr));
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap64Barrier(
+        old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  // The lib kern interface does not distinguish between
+  // Acquire and Release memory barriers; they are equivalent.
+  return Acquire_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
+  Atomic64 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#endif  // defined(__LP64__)
+
+}   // namespace base::subtle
+}   // namespace base
+
+#endif  // BASE_ATOMICOPS_INTERNALS_X86_MACOSX_H_
diff --git a/base/atomicops_internals_x86_msvc.h b/base/atomicops_internals_x86_msvc.h
new file mode 100644 (file)
index 0000000..1574528
--- /dev/null
@@ -0,0 +1,181 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is an internal atomic implementation, use base/atomicops.h instead.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
+#define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
+#pragma once
+
+#include <windows.h>
+
+namespace base {
+namespace subtle {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  LONG result = InterlockedCompareExchange(
+      reinterpret_cast<volatile LONG*>(ptr),
+      static_cast<LONG>(new_value),
+      static_cast<LONG>(old_value));
+  return static_cast<Atomic32>(result);
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  LONG result = InterlockedExchange(
+      reinterpret_cast<volatile LONG*>(ptr),
+      static_cast<LONG>(new_value));
+  return static_cast<Atomic32>(result);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  return InterlockedExchangeAdd(
+      reinterpret_cast<volatile LONG*>(ptr),
+      static_cast<LONG>(increment)) + increment;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
+#error "We require at least vs2005 for MemoryBarrier"
+#endif
+inline void MemoryBarrier() {
+  // We use MemoryBarrier from WinNT.h
+  ::MemoryBarrier();
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  NoBarrier_AtomicExchange(ptr, value);
+              // acts as a barrier in this implementation
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value; // works w/o barrier for current Intel chips as of June 2005
+  // See comments in Atomic64 version of Release_Store() below.
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#if defined(_WIN64)
+
+// 64-bit low-level operations on 64-bit platform.
+
+COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  PVOID result = InterlockedCompareExchangePointer(
+    reinterpret_cast<volatile PVOID*>(ptr),
+    reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
+  return reinterpret_cast<Atomic64>(result);
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  PVOID result = InterlockedExchangePointer(
+    reinterpret_cast<volatile PVOID*>(ptr),
+    reinterpret_cast<PVOID>(new_value));
+  return reinterpret_cast<Atomic64>(result);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  return InterlockedExchangeAdd64(
+      reinterpret_cast<volatile LONGLONG*>(ptr),
+      static_cast<LONGLONG>(increment)) + increment;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  NoBarrier_AtomicExchange(ptr, value);
+              // acts as a barrier in this implementation
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value; // works w/o barrier for current Intel chips as of June 2005
+
+  // When new chips come out, check:
+  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+  //  System Programming Guide, Chatper 7: Multiple-processor management,
+  //  Section 7.2, Memory Ordering.
+  // Last seen at:
+  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+
+#endif  // defined(_WIN64)
+
+}  // namespace base::subtle
+}  // namespace base
+
+#endif  // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
diff --git a/base/base_export.h b/base/base_export.h
new file mode 100644 (file)
index 0000000..c3bff9f
--- /dev/null
@@ -0,0 +1,26 @@
+// 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_OSP_EXPORT_
+#define BASE_BASE_OSP_EXPORT_
+#pragma once
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(BASE_IMPLEMENTATION)
+#define BASE_EXPORT __declspec(dllexport)
+#else
+#define BASE_EXPORT __declspec(dllimport)
+#endif  // defined(BASE_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#define BASE_EXPORT __attribute__((visibility("default")))
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define BASE_EXPORT
+#endif
+
+#endif  // BASE_BASE_OSP_EXPORT_
diff --git a/base/basictypes.h b/base/basictypes.h
new file mode 100644 (file)
index 0000000..c6f5097
--- /dev/null
@@ -0,0 +1,367 @@
+// 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_BASICTYPES_H_
+#define BASE_BASICTYPES_H_
+#pragma once
+
+#include <limits.h>         // So we can set the bounds of our types
+#include <stddef.h>         // For size_t
+#include <string.h>         // for memcpy
+
+#include "base/port.h"    // Types that only need exist on certain systems
+
+#ifndef COMPILER_MSVC
+// stdint.h is part of C99 but MSVC doesn't have it.
+#include <stdint.h>         // For intptr_t.
+#endif
+
+typedef signed char         schar;
+typedef signed char         int8;
+typedef short               int16;
+// TODO: Remove these type guards.  These are to avoid conflicts with
+// obsolete/protypes.h in the Gecko SDK.
+#ifndef _INT32
+#define _INT32
+typedef int                 int32;
+#endif
+
+// 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;
+#endif
+
+// NOTE: unsigned types are DANGEROUS in loops and other arithmetical
+// places.  Use the signed types unless your variable represents a bit
+// pattern (eg a hash value) or you really need the extra bit.  Do NOT
+// use 'unsigned' to express "this value should always be positive";
+// use assertions for this.
+
+typedef unsigned char      uint8;
+typedef unsigned short     uint16;
+// TODO: Remove these type guards.  These are to avoid conflicts with
+// obsolete/protypes.h in the Gecko SDK.
+#ifndef _UINT32
+#define _UINT32
+typedef unsigned int       uint32;
+#endif
+
+// See the comment above about NSPR and 64-bit.
+#if defined(__LP64__) && !defined(OS_MACOSX)
+typedef unsigned long uint64;
+#else
+typedef unsigned long long uint64;
+#endif
+
+// A type to represent a Unicode code-point value. As of Unicode 4.0,
+// such values require up to 21 bits.
+// (For type-checking on pointers, make this explicitly signed,
+// and it should always be the signed version of whatever int32 is.)
+typedef signed int         char32;
+
+const uint8  kuint8max  = (( uint8) 0xFF);
+const uint16 kuint16max = ((uint16) 0xFFFF);
+const uint32 kuint32max = ((uint32) 0xFFFFFFFF);
+const uint64 kuint64max = ((uint64) GG_LONGLONG(0xFFFFFFFFFFFFFFFF));
+const  int8  kint8min   = ((  int8) 0x80);
+const  int8  kint8max   = ((  int8) 0x7F);
+const  int16 kint16min  = (( int16) 0x8000);
+const  int16 kint16max  = (( int16) 0x7FFF);
+const  int32 kint32min  = (( int32) 0x80000000);
+const  int32 kint32max  = (( int32) 0x7FFFFFFF);
+const  int64 kint64min  = (( int64) GG_LONGLONG(0x8000000000000000));
+const  int64 kint64max  = (( int64) GG_LONGLONG(0x7FFFFFFFFFFFFFFF));
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+// An older, deprecated, politically incorrect name for the above.
+// NOTE: The usage of this macro was baned from our code base, but some
+// third_party libraries are yet using it.
+// TODO(tfarina): Figure out how to fix the usage of this macro in the
+// third_party libraries and get rid of it.
+#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+  TypeName();                                    \
+  DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+// The arraysize(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example.  If you use arraysize on
+// a pointer by mistake, you will get a compile-time error.
+//
+// One caveat is that arraysize() doesn't accept any array of an
+// anonymous type or a type defined inside a function.  In these rare
+// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below.  This is
+// due to a limitation in C++'s template system.  The limitation might
+// eventually be removed, but it hasn't happened yet.
+
+// This template function declaration is used in defining arraysize.
+// Note that the function doesn't need an implementation, as we only
+// use its type.
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N];
+
+// That gcc wants both of these prototypes seems mysterious. VC, for
+// its part, can't decide which to use (another mystery). Matching of
+// template overloads: the final frontier.
+#ifndef _MSC_VER
+template <typename T, size_t N>
+char (&ArraySizeHelper(const T (&array)[N]))[N];
+#endif
+
+#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+
+// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
+// but can be used on anonymous types or types defined inside
+// functions.  It's less safe than arraysize as it accepts some
+// (although not all) pointers.  Therefore, you should use arraysize
+// whenever possible.
+//
+// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type
+// size_t.
+//
+// ARRAYSIZE_UNSAFE catches a few type errors.  If you see a compiler error
+//
+//   "warning: division by zero in ..."
+//
+// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer.
+// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays.
+//
+// The following comments are on the implementation details, and can
+// be ignored by the users.
+//
+// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in
+// the array) and sizeof(*(arr)) (the # of bytes in one array
+// element).  If the former is divisible by the latter, perhaps arr is
+// indeed an array, in which case the division result is the # of
+// elements in the array.  Otherwise, arr cannot possibly be an array,
+// and we generate a compiler error to prevent the code from
+// compiling.
+//
+// Since the size of bool is implementation-defined, we need to cast
+// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
+// result has type size_t.
+//
+// This macro is not perfect as it wrongfully accepts certain
+// pointers, namely where the pointer size is divisible by the pointee
+// size.  Since all our code has to go through a 32-bit compiler,
+// where a pointer is 4 bytes, this means all pointers to a type whose
+// size is 3 or greater than 4 will be (righteously) rejected.
+
+#define ARRAYSIZE_UNSAFE(a) \
+  ((sizeof(a) / sizeof(*(a))) / \
+   static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+
+// Use implicit_cast as a safe version of static_cast or const_cast
+// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
+// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
+// a const pointer to Foo).
+// When you use implicit_cast, the compiler checks that the cast is safe.
+// Such explicit implicit_casts are necessary in surprisingly many
+// situations where C++ demands an exact type match instead of an
+// argument type convertable to a target type.
+//
+// The From type can be inferred, so the preferred syntax for using
+// implicit_cast is the same as for static_cast etc.:
+//
+//   implicit_cast<ToType>(expr)
+//
+// implicit_cast would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+template<typename To, typename From>
+inline To implicit_cast(From const &f) {
+  return f;
+}
+
+// The COMPILE_ASSERT macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES,
+//                  content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#undef COMPILE_ASSERT
+#define COMPILE_ASSERT(expr, msg) \
+  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
+// Implementation details of COMPILE_ASSERT:
+//
+// - COMPILE_ASSERT works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//     #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
+//                               // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     COMPILE_ASSERT(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+
+// MetatagId refers to metatag-id that we assign to
+// each metatag <name, value> pair..
+typedef uint32 MetatagId;
+
+// Argument type used in interfaces that can optionally take ownership
+// of a passed in argument.  If TAKE_OWNERSHIP is passed, the called
+// object takes ownership of the argument.  Otherwise it does not.
+enum Ownership {
+  DO_NOT_TAKE_OWNERSHIP,
+  TAKE_OWNERSHIP
+};
+
+// bit_cast<Dest,Source> is a template function that implements the
+// equivalent of "*reinterpret_cast<Dest*>(&source)".  We need this in
+// very low-level functions like the protobuf library and fast math
+// support.
+//
+//   float f = 3.14159265358979;
+//   int i = bit_cast<int32>(f);
+//   // i = 0x40490fdb
+//
+// The classical address-casting method is:
+//
+//   // WRONG
+//   float f = 3.14159265358979;            // WRONG
+//   int i = * reinterpret_cast<int*>(&f);  // WRONG
+//
+// The address-casting method actually produces undefined behavior
+// according to ISO C++ specification section 3.10 -15 -.  Roughly, this
+// section says: if an object in memory has one type, and a program
+// accesses it with a different type, then the result is undefined
+// behavior for most values of "different type".
+//
+// This is true for any cast syntax, either *(int*)&f or
+// *reinterpret_cast<int*>(&f).  And it is particularly true for
+// conversions betweeen integral lvalues and floating-point lvalues.
+//
+// The purpose of 3.10 -15- is to allow optimizing compilers to assume
+// that expressions with different types refer to different memory.  gcc
+// 4.0.1 has an optimizer that takes advantage of this.  So a
+// non-conforming program quietly produces wildly incorrect output.
+//
+// The problem is not the use of reinterpret_cast.  The problem is type
+// punning: holding an object in memory of one type and reading its bits
+// back using a different type.
+//
+// The C++ standard is more subtle and complex than this, but that
+// is the basic idea.
+//
+// Anyways ...
+//
+// bit_cast<> calls memcpy() which is blessed by the standard,
+// especially by the example in section 3.9 .  Also, of course,
+// bit_cast<> wraps up the nasty logic in one place.
+//
+// Fortunately memcpy() is very fast.  In optimized mode, with a
+// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
+// code with the minimal amount of data movement.  On a 32-bit system,
+// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
+// compiles to two loads and two stores.
+//
+// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
+//
+// WARNING: if Dest or Source is a non-POD type, the result of the memcpy
+// is likely to surprise you.
+
+template <class Dest, class Source>
+inline Dest bit_cast(const Source& source) {
+  // Compile time assertion: sizeof(Dest) == sizeof(Source)
+  // A compile error here means your Dest and Source have different sizes.
+  typedef char VerifySizesAreEqual [sizeof(Dest) == sizeof(Source) ? 1 : -1];
+
+  Dest dest;
+  memcpy(&dest, &source, sizeof(dest));
+  return dest;
+}
+
+// Used to explicitly mark the return value of a function as unused. If you are
+// really sure you don't want to do anything with the return value of a function
+// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example:
+//
+//   scoped_ptr<MyType> my_var = ...;
+//   if (TakeOwnership(my_var.get()) == SUCCESS)
+//     ignore_result(my_var.release());
+//
+template<typename T>
+inline void ignore_result(const T& ignored) {
+}
+
+// The following enum should be used only as a constructor argument to indicate
+// that the variable has static storage class, and that the constructor should
+// do nothing to its state.  It indicates to the reader that it is legal to
+// declare a static instance of the class, provided the constructor is given
+// the base::LINKER_INITIALIZED argument.  Normally, it is unsafe to declare a
+// static variable that has a constructor or a destructor because invocation
+// order is undefined.  However, IF the type can be initialized by filling with
+// zeroes (which the loader does for static variables), AND the destructor also
+// does nothing to the storage, AND there are no virtual methods, then a
+// constructor declared as
+//       explicit MyClass(base::LinkerInitialized x) {}
+// and invoked as
+//       static MyClass my_variable_name(base::LINKER_INITIALIZED);
+namespace base {
+enum LinkerInitialized { LINKER_INITIALIZED };
+}  // base
+
+#endif  // BASE_BASICTYPES_H_
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
new file mode 100644 (file)
index 0000000..0a6e05a
--- /dev/null
@@ -0,0 +1,140 @@
+// 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_COMPILER_SPECIFIC_H_
+#define BASE_COMPILER_SPECIFIC_H_
+#pragma once
+
+#include "build/build_config.h"
+
+#if defined(COMPILER_MSVC)
+
+// Macros for suppressing and disabling warnings on MSVC.
+//
+// Warning numbers are enumerated at:
+// http://msdn.microsoft.com/en-us/library/8x5x43k7(VS.80).aspx
+//
+// The warning pragma:
+// http://msdn.microsoft.com/en-us/library/2c8f766e(VS.80).aspx
+//
+// Using __pragma instead of #pragma inside macros:
+// http://msdn.microsoft.com/en-us/library/d9x1s805.aspx
+
+// MSVC_SUPPRESS_WARNING disables warning |n| for the remainder of the line and
+// for the next line of the source file.
+#define MSVC_SUPPRESS_WARNING(n) __pragma(warning(suppress:n))
+
+// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled.
+// The warning remains disabled until popped by MSVC_POP_WARNING.
+#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
+                                     __pragma(warning(disable:n))
+
+// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level.  The level
+// remains in effect until popped by MSVC_POP_WARNING().  Use 0 to disable all
+// warnings.
+#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n))
+
+// Pop effects of innermost MSVC_PUSH_* macro.
+#define MSVC_POP_WARNING() __pragma(warning(pop))
+
+#define MSVC_DISABLE_OPTIMIZE() __pragma(optimize("", off))
+#define MSVC_ENABLE_OPTIMIZE() __pragma(optimize("", on))
+
+// Allows |this| to be passed as an argument in constructor initializer lists.
+// This uses push/pop instead of the seemingly simpler suppress feature to avoid
+// having the warning be disabled for more than just |code|.
+//
+// Example usage:
+// Foo::Foo() : x(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(y(this)), z(3) {}
+//
+// Compiler warning C4355: 'this': used in base member initializer list:
+// http://msdn.microsoft.com/en-us/library/3c594ae3(VS.80).aspx
+#define ALLOW_THIS_IN_INITIALIZER_LIST(code) MSVC_PUSH_DISABLE_WARNING(4355) \
+                                             code \
+                                             MSVC_POP_WARNING()
+
+// Allows exporting a class that inherits from a non-exported base class.
+// This uses suppress instead of push/pop because the delimiter after the
+// declaration (either "," or "{") has to be placed before the pop macro.
+//
+// Example usage:
+// class EXPORT_API Foo : NON_EXPORTED_BASE(public Bar) {
+//
+// MSVC Compiler warning C4275:
+// non dll-interface class 'Bar' used as base for dll-interface class 'Foo'.
+// Note that this is intended to be used only when no access to the base class
+// can be gained through the derived class. For more info, see
+// http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
+#define NON_EXPORTED_BASE(code) MSVC_SUPPRESS_WARNING(4275) \
+                                code
+
+#else  // Not MSVC
+
+#define MSVC_SUPPRESS_WARNING(n)
+#define MSVC_PUSH_DISABLE_WARNING(n)
+#define MSVC_PUSH_WARNING_LEVEL(n)
+#define MSVC_POP_WARNING()
+#define MSVC_DISABLE_OPTIMIZE()
+#define MSVC_ENABLE_OPTIMIZE()
+#define ALLOW_THIS_IN_INITIALIZER_LIST(code) code
+#define NON_EXPORTED_BASE(code) code
+
+#endif  // COMPILER_MSVC
+
+
+// Annotate a variable indicating it's ok if the variable is not used.
+// (Typically used to silence a compiler warning when the assignment
+// is important for some other reason.)
+// Use like:
+//   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
+// method in the parent class.
+// Use like:
+//   virtual void foo() OVERRIDE;
+#if defined(COMPILER_MSVC)
+#define OVERRIDE override
+#elif defined(__clang__)
+#define OVERRIDE override
+#else
+#define OVERRIDE
+#endif
+
+// Annotate a function indicating the caller must examine the return value.
+// Use like:
+//   int foo() WARN_UNUSED_RESULT;
+// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
+#if defined(COMPILER_GCC)
+#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define WARN_UNUSED_RESULT
+#endif
+
+// Tell the compiler a function is using a printf-style format string.
+// |format_param| is the one-based index of the format string parameter;
+// |dots_param| is the one-based index of the "..." parameter.
+// For v*printf functions (which take a va_list), pass 0 for dots_param.
+// (This is undocumented but matches what the system C headers do.)
+#if defined(COMPILER_GCC)
+#define PRINTF_FORMAT(format_param, dots_param) \
+    __attribute__((format(printf, format_param, dots_param)))
+#else
+#define PRINTF_FORMAT(format_param, dots_param)
+#endif
+
+// WPRINTF_FORMAT is the same, but for wide format strings.
+// This doesn't appear to yet be implemented in any compiler.
+// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38308 .
+#define WPRINTF_FORMAT(format_param, dots_param)
+// If available, it would look like:
+//   __attribute__((format(wprintf, format_param, dots_param)))
+
+#endif  // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/file_descriptor_posix.h b/base/file_descriptor_posix.h
new file mode 100644 (file)
index 0000000..6f46ab4
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (c) 2006-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_FILE_DESCRIPTOR_POSIX_H_
+#define BASE_FILE_DESCRIPTOR_POSIX_H_
+#pragma once
+
+namespace base {
+
+// -----------------------------------------------------------------------------
+// We introduct a special structure for file descriptors in order that we are
+// able to use template specialisation to special-case their handling.
+//
+// WARNING: (Chromium only) There are subtleties to consider if serialising
+// these objects over IPC. See comments in ipc/ipc_message_utils.h
+// above the template specialisation for this structure.
+// -----------------------------------------------------------------------------
+struct FileDescriptor {
+  FileDescriptor()
+      : fd(-1),
+        auto_close(false) { }
+
+  FileDescriptor(int ifd, bool iauto_close)
+      : fd(ifd),
+        auto_close(iauto_close) { }
+
+  bool operator==(const FileDescriptor& other) const {
+    return (fd == other.fd && auto_close == other.auto_close);
+  }
+
+  // A comparison operator so that we can use these as keys in a std::map.
+  bool operator<(const FileDescriptor& other) const {
+    return other.fd < fd;
+  }
+
+  int fd;
+  // If true, this file descriptor should be closed after it has been used. For
+  // example an IPC system might interpret this flag as indicating that the
+  // file descriptor it has been given should be closed after use.
+  bool auto_close;
+};
+
+}  // namespace base
+
+#endif  // BASE_FILE_DESCRIPTOR_POSIX_H_
diff --git a/base/hash_tables.h b/base/hash_tables.h
new file mode 100644 (file)
index 0000000..b91d5d4
--- /dev/null
@@ -0,0 +1,120 @@
+// 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.
+//
+
+//
+// Deal with the differences between Microsoft and GNU implemenations
+// of hash_map. Allows all platforms to use |base::hash_map| and
+// |base::hash_set|.
+//  eg:
+//   base::hash_map<int> my_map;
+//   base::hash_set<int> my_set;
+//
+// NOTE: It is an explicit non-goal of this class to provide a generic hash
+// function for pointers.  If you want to hash a pointers to a particular class,
+// please define the template specialization elsewhere (for example, in its
+// header file) and keep it specific to just pointers to that class.  This is
+// because identity hashes are not desirable for all types that might show up
+// in containers as pointers.
+
+#ifndef BASE_HASH_TABLES_H_
+#define BASE_HASH_TABLES_H_
+#pragma once
+
+#include "build/build_config.h"
+
+#include "base/string16.h"
+
+#if defined(COMPILER_MSVC)
+#include <hash_map>
+#include <hash_set>
+
+#define BASE_HASH_NAMESPACE stdext
+
+#elif defined(COMPILER_GCC)
+#if defined(OS_ANDROID)
+#define BASE_HASH_NAMESPACE std
+#else
+#define BASE_HASH_NAMESPACE __gnu_cxx
+#endif
+
+// This is a hack to disable the gcc 4.4 warning about hash_map and hash_set
+// being deprecated.  We can get rid of this when we upgrade to VS2008 and we
+// can use <tr1/unordered_map> and <tr1/unordered_set>.
+#ifdef __DEPRECATED
+#define CHROME_OLD__DEPRECATED __DEPRECATED
+#undef __DEPRECATED
+#endif
+
+#if defined(OS_ANDROID)
+#include <hash_map>
+#include <hash_set>
+#else
+#include <ext/hash_map>
+#include <ext/hash_set>
+#endif
+
+#include <string>
+
+#ifdef CHROME_OLD__DEPRECATED
+#define __DEPRECATED CHROME_OLD__DEPRECATED
+#undef CHROME_OLD__DEPRECATED
+#endif
+
+namespace BASE_HASH_NAMESPACE {
+
+#if !defined(OS_ANDROID)
+// The GNU C++ library provides identity hash functions for many integral types,
+// but not for |long long|.  This hash function will truncate if |size_t| is
+// narrower than |long long|.  This is probably good enough for what we will
+// use it for.
+
+#define DEFINE_TRIVIAL_HASH(integral_type) \
+    template<> \
+    struct hash<integral_type> { \
+      std::size_t operator()(integral_type value) const { \
+        return static_cast<std::size_t>(value); \
+      } \
+    }
+
+DEFINE_TRIVIAL_HASH(long long);
+DEFINE_TRIVIAL_HASH(unsigned long long);
+
+#undef DEFINE_TRIVIAL_HASH
+#endif  // !defined(OS_ANDROID)
+
+// Implement string hash functions so that strings of various flavors can
+// be used as keys in STL maps and sets.  The hash algorithm comes from the
+// GNU C++ library, in <tr1/functional>.  It is duplicated here because GCC
+// versions prior to 4.3.2 are unable to compile <tr1/functional> when RTTI
+// is disabled, as it is in our build.
+
+#define DEFINE_STRING_HASH(string_type) \
+    template<> \
+    struct hash<string_type> { \
+      std::size_t operator()(const string_type& s) const { \
+        std::size_t result = 0; \
+        for (string_type::const_iterator i = s.begin(); i != s.end(); ++i) \
+          result = (result * 131) + *i; \
+        return result; \
+      } \
+    }
+
+DEFINE_STRING_HASH(std::string);
+DEFINE_STRING_HASH(string16);
+
+#undef DEFINE_STRING_HASH
+
+}  // namespace BASE_HASH_NAMESPACE
+
+#else  // COMPILER
+#error define BASE_HASH_NAMESPACE for your compiler
+#endif  // COMPILER
+
+namespace base {
+using BASE_HASH_NAMESPACE::hash_map;
+using BASE_HASH_NAMESPACE::hash_set;
+}
+
+#endif  // BASE_HASH_TABLES_H_
diff --git a/base/logging.h b/base/logging.h
new file mode 100644 (file)
index 0000000..c18fada
--- /dev/null
@@ -0,0 +1,952 @@
+// 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_LOGGING_H_
+#define BASE_LOGGING_H_
+#pragma once
+
+#include <cassert>
+#include <string>
+#include <cstring>
+#include <sstream>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "build/build_config.h"
+
+//
+// Optional message capabilities
+// -----------------------------
+// Assertion failed messages and fatal errors are displayed in a dialog box
+// before the application exits. However, running this UI creates a message
+// loop, which causes application messages to be processed and potentially
+// dispatched to existing application windows. Since the application is in a
+// bad state when this assertion dialog is displayed, these messages may not
+// get processed and hang the dialog, or the application might go crazy.
+//
+// Therefore, it can be beneficial to display the error dialog in a separate
+// process from the main application. When the logging system needs to display
+// a fatal error dialog box, it will look for a program called
+// "DebugMessage.exe" in the same directory as the application executable. It
+// will run this application with the message as the command line, and will
+// not include the name of the application as is traditional for easier
+// parsing.
+//
+// The code for DebugMessage.exe is only one line. In WinMain, do:
+//   MessageBox(NULL, GetCommandLineW(), L"Fatal Error", 0);
+//
+// If DebugMessage.exe is not found, the logging code will use a normal
+// MessageBox, potentially causing the problems discussed above.
+
+
+// Instructions
+// ------------
+//
+// Make a bunch of macros for logging.  The way to log things is to stream
+// things to LOG(<a particular severity level>).  E.g.,
+//
+//   LOG(INFO) << "Found " << num_cookies << " cookies";
+//
+// You can also do conditional logging:
+//
+//   LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+//
+// The above will cause log messages to be output on the 1st, 11th, 21st, ...
+// times it is executed.  Note that the special COUNTER value is used to
+// identify which repetition is happening.
+//
+// The CHECK(condition) macro is active in both debug and release builds and
+// effectively performs a LOG(FATAL) which terminates the process and
+// generates a crashdump unless a debugger is attached.
+//
+// There are also "debug mode" logging macros like the ones above:
+//
+//   DLOG(INFO) << "Found cookies";
+//
+//   DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+//
+// All "debug mode" logging is compiled away to nothing for non-debug mode
+// compiles.  LOG_IF and development flags also work well together
+// because the code can be compiled away sometimes.
+//
+// We also have
+//
+//   LOG_ASSERT(assertion);
+//   DLOG_ASSERT(assertion);
+//
+// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
+//
+// There are "verbose level" logging macros.  They look like
+//
+//   VLOG(1) << "I'm printed when you run the program with --v=1 or more";
+//   VLOG(2) << "I'm printed when you run the program with --v=2 or more";
+//
+// These always log at the INFO log level (when they log at all).
+// The verbose logging can also be turned on module-by-module.  For instance,
+//    --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0
+// will cause:
+//   a. VLOG(2) and lower messages to be printed from profile.{h,cc}
+//   b. VLOG(1) and lower messages to be printed from icon_loader.{h,cc}
+//   c. VLOG(3) and lower messages to be printed from files prefixed with
+//      "browser"
+//   d. VLOG(4) and lower messages to be printed from files under a
+//     "chromeos" directory.
+//   e. VLOG(0) and lower messages to be printed from elsewhere
+//
+// The wildcarding functionality shown by (c) supports both '*' (match
+// 0 or more characters) and '?' (match any single character)
+// wildcards.  Any pattern containing a forward or backward slash will
+// be tested against the whole pathname and not just the module.
+// E.g., "*/foo/bar/*=2" would change the logging level for all code
+// in source files under a "foo/bar" directory.
+//
+// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
+//
+//   if (VLOG_IS_ON(2)) {
+//     // do some logging preparation and logging
+//     // that can't be accomplished with just VLOG(2) << ...;
+//   }
+//
+// There is also a VLOG_IF "verbose level" condition macro for sample
+// cases, when some extra computation and preparation for logs is not
+// needed.
+//
+//   VLOG_IF(1, (size > 1024))
+//      << "I'm printed when size is more than 1024 and when you run the "
+//         "program with --v=1 or more";
+//
+// We also override the standard 'assert' to use 'DLOG_ASSERT'.
+//
+// Lastly, there is:
+//
+//   PLOG(ERROR) << "Couldn't do foo";
+//   DPLOG(ERROR) << "Couldn't do foo";
+//   PLOG_IF(ERROR, cond) << "Couldn't do foo";
+//   DPLOG_IF(ERROR, cond) << "Couldn't do foo";
+//   PCHECK(condition) << "Couldn't do foo";
+//   DPCHECK(condition) << "Couldn't do foo";
+//
+// which append the last system error to the message in string form (taken from
+// GetLastError() on Windows and errno on POSIX).
+//
+// The supported severity levels for macros that allow you to specify one
+// are (in increasing order of severity) INFO, WARNING, ERROR, ERROR_REPORT,
+// and FATAL.
+//
+// Very important: logging a message at the FATAL severity level causes
+// the program to terminate (after the message is logged).
+//
+// Note the special severity of ERROR_REPORT only available/relevant in normal
+// mode, which displays error dialog without terminating the program. There is
+// no error dialog for severity ERROR or below in normal mode.
+//
+// There is also the special severity of DFATAL, which logs FATAL in
+// debug mode, ERROR in normal mode.
+
+namespace logging {
+
+// Where to record logging output? A flat file and/or system debug log via
+// OutputDebugString. Defaults on Windows to LOG_ONLY_TO_FILE, and on
+// POSIX to LOG_ONLY_TO_SYSTEM_DEBUG_LOG (aka stderr).
+enum LoggingDestination { LOG_NONE,
+                          LOG_ONLY_TO_FILE,
+                          LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
+                          LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG };
+
+// Indicates that the log file should be locked when being written to.
+// Often, there is no locking, which is fine for a single threaded program.
+// If logging is being done from multiple threads or there can be more than
+// one process doing the logging, the file should be locked during writes to
+// make each log outut atomic. Other writers will block.
+//
+// All processes writing to the log file must have their locking set for it to
+// work properly. Defaults to DONT_LOCK_LOG_FILE.
+enum LogLockingState { LOCK_LOG_FILE, DONT_LOCK_LOG_FILE };
+
+// On startup, should we delete or append to an existing log file (if any)?
+// Defaults to APPEND_TO_OLD_LOG_FILE.
+enum OldFileDeletionState { DELETE_OLD_LOG_FILE, APPEND_TO_OLD_LOG_FILE };
+
+enum DcheckState {
+  DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS,
+  ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS
+};
+
+// TODO(avi): do we want to do a unification of character types here?
+#if defined(OS_WIN)
+typedef wchar_t PathChar;
+#else
+typedef char PathChar;
+#endif
+
+// Define different names for the BaseInitLoggingImpl() function depending on
+// whether NDEBUG is defined or not so that we'll fail to link if someone tries
+// to compile logging.cc with NDEBUG but includes logging.h without defining it,
+// or vice versa.
+#if NDEBUG
+#define BaseInitLoggingImpl BaseInitLoggingImpl_built_with_NDEBUG
+#else
+#define BaseInitLoggingImpl BaseInitLoggingImpl_built_without_NDEBUG
+#endif
+
+// 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".
+BASE_EXPORT 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.
+// If you don't call it, all the flags will be initialized to their default
+// values, and there is a race condition that may leak a critical section
+// object if two threads try to do the first log at the same time.
+// See the definition of the enums above for descriptions and default values.
+//
+// The default log file is initialized to "debug.log" in the application
+// directory. You probably don't want this, especially since the program
+// directory may not be writable on an enduser's system.
+inline bool InitLogging(const PathChar* log_file,
+                        LoggingDestination logging_dest,
+                        LogLockingState lock_log,
+                        OldFileDeletionState delete_old,
+                        DcheckState dcheck_state) {
+  return BaseInitLoggingImpl(log_file, logging_dest, lock_log,
+                             delete_old, dcheck_state);
+}
+
+// Sets the log level. Anything at or above this level will be written to the
+// log file/displayed to the user (if applicable). Anything below this level
+// will be silently ignored. The log level defaults to 0 (everything is logged
+// 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.
+BASE_EXPORT void SetMinLogLevel(int level);
+
+// Gets the current log level.
+BASE_EXPORT int GetMinLogLevel();
+
+// Gets the VLOG default verbosity level.
+BASE_EXPORT 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.
+BASE_EXPORT int GetVlogLevelHelper(const char* file_start, size_t N);
+
+template <size_t N>
+int GetVlogLevel(const char (&file)[N]) {
+  return GetVlogLevelHelper(file, N);
+}
+
+// Sets the common items you want to be prepended to each log message.
+// 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.
+BASE_EXPORT 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.
+BASE_EXPORT 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);
+BASE_EXPORT 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);
+BASE_EXPORT 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).
+// Returns true to signal that it handled the message and the message
+// 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);
+BASE_EXPORT void SetLogMessageHandler(LogMessageHandlerFunction handler);
+BASE_EXPORT LogMessageHandlerFunction GetLogMessageHandler();
+
+typedef int LogSeverity;
+const LogSeverity LOG_VERBOSE = -1;  // This is level 1 verbosity
+// Note: the log severities are used to index into the array of names,
+// see log_severity_names.
+const LogSeverity LOG_INFO = 0;
+const LogSeverity LOG_WARNING = 1;
+const LogSeverity LOG_ERROR = 2;
+const LogSeverity LOG_ERROR_REPORT = 3;
+const LogSeverity LOG_FATAL = 4;
+const LogSeverity LOG_NUM_SEVERITIES = 5;
+
+// LOG_DFATAL is LOG_FATAL in debug mode, ERROR in normal mode
+#ifdef NDEBUG
+const LogSeverity LOG_DFATAL = LOG_ERROR;
+#else
+const LogSeverity LOG_DFATAL = LOG_FATAL;
+#endif
+
+// A few definitions of macros that don't generate much code. These are used
+// by LOG() and LOG_IF, etc. Since these are used all over our code, it's
+// better to have compact code for these operations.
+#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
+  logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
+  logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
+  logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName, ...) \
+  logging::ClassName(__FILE__, __LINE__, \
+                     logging::LOG_ERROR_REPORT , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
+  logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
+  logging::ClassName(__FILE__, __LINE__, logging::LOG_DFATAL , ##__VA_ARGS__)
+
+#define COMPACT_GOOGLE_LOG_INFO \
+  COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
+#define COMPACT_GOOGLE_LOG_WARNING \
+  COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage)
+#define COMPACT_GOOGLE_LOG_ERROR \
+  COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage)
+#define COMPACT_GOOGLE_LOG_ERROR_REPORT \
+  COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(LogMessage)
+#define COMPACT_GOOGLE_LOG_FATAL \
+  COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage)
+#define COMPACT_GOOGLE_LOG_DFATAL \
+  COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage)
+
+// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
+// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
+// to keep using this syntax, we define this macro to do the same thing
+// as COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that
+// the Windows SDK does for consistency.
+#define ERROR 0
+#define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \
+  COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
+// Needed for LOG_IS_ON(ERROR).
+const LogSeverity LOG_0 = LOG_ERROR;
+
+// As special cases, we can assume that LOG_IS_ON(ERROR_REPORT) and
+// LOG_IS_ON(FATAL) always hold.  Also, LOG_IS_ON(DFATAL) always holds
+// in debug mode.  In particular, CHECK()s will always fire if they
+// fail.
+#define LOG_IS_ON(severity) \
+  ((::logging::LOG_ ## severity) >= ::logging::GetMinLogLevel())
+
+// We can't do any caching tricks with VLOG_IS_ON() like the
+// google-glog version since it requires GCC extensions.  This means
+// that using the v-logging functions in conjunction with --vmodule
+// may be slow.
+#define VLOG_IS_ON(verboselevel) \
+  ((verboselevel) <= ::logging::GetVlogLevel(__FILE__))
+
+// Helper macro which avoids evaluating the arguments to a stream if
+// the condition doesn't hold.
+#define LAZY_STREAM(stream, condition)                                  \
+  !(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream)
+
+// We use the preprocessor's merging operator, "##", so that, e.g.,
+// LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO.  There's some funny
+// subtle difference between ostream member streaming functions (e.g.,
+// ostream::operator<<(int) and ostream non-member streaming functions
+// (e.g., ::operator<<(ostream&, string&): it turns out that it's
+// impossible to stream something like a string directly to an unnamed
+// ostream. We employ a neat hack by calling the stream() member
+// function of LogMessage which seems to avoid the problem.
+#define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
+
+#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity))
+#define LOG_IF(severity, condition) \
+  LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
+
+#define SYSLOG(severity) LOG(severity)
+#define SYSLOG_IF(severity, condition) LOG_IF(severity, condition)
+
+// The VLOG macros log with negative verbosities.
+#define VLOG_STREAM(verbose_level) \
+  logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream()
+
+#define VLOG(verbose_level) \
+  LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
+
+#define VLOG_IF(verbose_level, condition) \
+  LAZY_STREAM(VLOG_STREAM(verbose_level), \
+      VLOG_IS_ON(verbose_level) && (condition))
+
+#if defined (OS_WIN)
+#define VPLOG_STREAM(verbose_level) \
+  logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \
+    ::logging::GetLastSystemErrorCode()).stream()
+#elif defined(OS_POSIX)
+#define VPLOG_STREAM(verbose_level) \
+  logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \
+    ::logging::GetLastSystemErrorCode()).stream()
+#endif
+
+#define VPLOG(verbose_level) \
+  LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
+
+#define VPLOG_IF(verbose_level, condition) \
+  LAZY_STREAM(VPLOG_STREAM(verbose_level), \
+    VLOG_IS_ON(verbose_level) && (condition))
+
+// TODO(akalin): Add more VLOG variants, e.g. VPLOG.
+
+#define LOG_ASSERT(condition)  \
+  LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
+#define SYSLOG_ASSERT(condition) \
+  SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
+
+#if defined(OS_WIN)
+#define LOG_GETLASTERROR_STREAM(severity) \
+  COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \
+      ::logging::GetLastSystemErrorCode()).stream()
+#define LOG_GETLASTERROR(severity) \
+  LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity), LOG_IS_ON(severity))
+#define LOG_GETLASTERROR_MODULE_STREAM(severity, module) \
+  COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \
+      ::logging::GetLastSystemErrorCode(), module).stream()
+#define LOG_GETLASTERROR_MODULE(severity, module)                       \
+  LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity, module),                \
+              LOG_IS_ON(severity))
+// PLOG_STREAM is used by PLOG, which is the usual error logging macro
+// for each platform.
+#define PLOG_STREAM(severity) LOG_GETLASTERROR_STREAM(severity)
+#elif defined(OS_POSIX)
+#define LOG_ERRNO_STREAM(severity) \
+  COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \
+      ::logging::GetLastSystemErrorCode()).stream()
+#define LOG_ERRNO(severity) \
+  LAZY_STREAM(LOG_ERRNO_STREAM(severity), LOG_IS_ON(severity))
+// PLOG_STREAM is used by PLOG, which is the usual error logging macro
+// for each platform.
+#define PLOG_STREAM(severity) LOG_ERRNO_STREAM(severity)
+// TODO(tschmelcher): Should we add OSStatus logging for Mac?
+#endif
+
+#define PLOG(severity)                                          \
+  LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity))
+
+#define PLOG_IF(severity, condition) \
+  LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
+
+// CHECK dies with a fatal error if condition is not true.  It is *not*
+// controlled by NDEBUG, so the check will be executed regardless of
+// compilation mode.
+//
+// We make sure CHECK et al. always evaluates their arguments, as
+// doing CHECK(FunctionWithSideEffect()) is a common idiom.
+#define CHECK(condition)                       \
+  LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \
+  << "Check failed: " #condition ". "
+
+#define PCHECK(condition) \
+  LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
+  << "Check failed: " #condition ". "
+
+// Build the error message string.  This is separate from the "Impl"
+// function template because it is not performance critical and so can
+// be out of line, while the "Impl" code should be inline.  Caller
+// takes ownership of the returned string.
+template<class t1, class t2>
+std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
+  std::ostringstream ss;
+  ss << names << " (" << v1 << " vs. " << v2 << ")";
+  std::string* msg = new std::string(ss.str());
+  return msg;
+}
+
+// MSVC doesn't like complex extern templates and DLLs.
+#if !defined(COMPILER_MSVC) && !defined(COMPONENT_BUILD)
+// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
+// in logging.cc.
+extern template std::string* MakeCheckOpString<int, int>(
+    const int&, const int&, const char* names);
+extern template std::string* MakeCheckOpString<unsigned long, unsigned long>(
+    const unsigned long&, const unsigned long&, const char* names);
+extern template std::string* MakeCheckOpString<unsigned long, unsigned int>(
+    const unsigned long&, const unsigned int&, const char* names);
+extern template std::string* MakeCheckOpString<unsigned int, unsigned long>(
+    const unsigned int&, const unsigned long&, const char* names);
+extern template std::string* MakeCheckOpString<std::string, std::string>(
+    const std::string&, const std::string&, const char* name);
+#endif
+
+// Helper macro for binary operators.
+// Don't use this macro directly in your code, use CHECK_EQ et al below.
+//
+// TODO(akalin): Rewrite this so that constructs like if (...)
+// CHECK_EQ(...) else { ... } work properly.
+#define CHECK_OP(name, op, val1, val2)                          \
+  if (std::string* _result =                                    \
+      logging::Check##name##Impl((val1), (val2),                \
+                                 #val1 " " #op " " #val2))      \
+    logging::LogMessage(__FILE__, __LINE__, _result).stream()
+
+// Helper functions for CHECK_OP macro.
+// The (int, int) specialization works around the issue that the compiler
+// will not instantiate the template version of the function on values of
+// unnamed enum type - see comment below.
+#define DEFINE_CHECK_OP_IMPL(name, op) \
+  template <class t1, class t2> \
+  inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
+                                        const char* names) { \
+    if (v1 op v2) return NULL; \
+    else return MakeCheckOpString(v1, v2, names); \
+  } \
+  inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
+    if (v1 op v2) return NULL; \
+    else return MakeCheckOpString(v1, v2, names); \
+  }
+DEFINE_CHECK_OP_IMPL(EQ, ==)
+DEFINE_CHECK_OP_IMPL(NE, !=)
+DEFINE_CHECK_OP_IMPL(LE, <=)
+DEFINE_CHECK_OP_IMPL(LT, < )
+DEFINE_CHECK_OP_IMPL(GE, >=)
+DEFINE_CHECK_OP_IMPL(GT, > )
+#undef DEFINE_CHECK_OP_IMPL
+
+#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
+#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
+#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
+#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
+#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
+#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
+
+// http://crbug.com/16512 is open for a real fix for this.  For now, Windows
+// uses OFFICIAL_BUILD and other platforms use the branding flag when NDEBUG is
+// defined.
+#if ( defined(OS_WIN) && defined(OFFICIAL_BUILD)) || \
+    (!defined(OS_WIN) && defined(NDEBUG) && defined(GOOGLE_CHROME_BUILD))
+// Used by unit tests.
+#define LOGGING_IS_OFFICIAL_BUILD
+
+// In order to have optimized code for official builds, remove DLOGs and
+// DCHECKs.
+#define ENABLE_DLOG 0
+#define ENABLE_DCHECK 0
+
+#elif defined(NDEBUG)
+// Otherwise, if we're a release build, remove DLOGs but not DCHECKs
+// (since those can still be turned on via a command-line flag).
+#define ENABLE_DLOG 0
+#define ENABLE_DCHECK 1
+
+#else
+// Otherwise, we're a debug build so enable DLOGs and DCHECKs.
+#define ENABLE_DLOG 1
+#define ENABLE_DCHECK 1
+#endif
+
+// Definitions for DLOG et al.
+
+#if ENABLE_DLOG
+
+#define DLOG_IS_ON(severity) LOG_IS_ON(severity)
+#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
+#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
+#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition)
+#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition)
+#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition)
+
+#else  // ENABLE_DLOG
+
+// If ENABLE_DLOG is off, we want to avoid emitting any references to
+// |condition| (which may reference a variable defined only if NDEBUG
+// is not defined).  Contrast this with DCHECK et al., which has
+// different behavior.
+
+#define DLOG_EAT_STREAM_PARAMETERS                                      \
+  true ? (void) 0 : ::logging::LogMessageVoidify() & LOG_STREAM(FATAL)
+
+#define DLOG_IS_ON(severity) false
+#define DLOG_IF(severity, condition) DLOG_EAT_STREAM_PARAMETERS
+#define DLOG_ASSERT(condition) DLOG_EAT_STREAM_PARAMETERS
+#define DPLOG_IF(severity, condition) DLOG_EAT_STREAM_PARAMETERS
+#define DVLOG_IF(verboselevel, condition) DLOG_EAT_STREAM_PARAMETERS
+#define DVPLOG_IF(verboselevel, condition) DLOG_EAT_STREAM_PARAMETERS
+
+#endif  // ENABLE_DLOG
+
+// DEBUG_MODE is for uses like
+//   if (DEBUG_MODE) foo.CheckThatFoo();
+// instead of
+//   #ifndef NDEBUG
+//     foo.CheckThatFoo();
+//   #endif
+//
+// We tie its state to ENABLE_DLOG.
+enum { DEBUG_MODE = ENABLE_DLOG };
+
+#undef ENABLE_DLOG
+
+#define DLOG(severity)                                          \
+  LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity))
+
+#if defined(OS_WIN)
+#define DLOG_GETLASTERROR(severity) \
+  LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity), DLOG_IS_ON(severity))
+#define DLOG_GETLASTERROR_MODULE(severity, module)                      \
+  LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity, module),                \
+              DLOG_IS_ON(severity))
+#elif defined(OS_POSIX)
+#define DLOG_ERRNO(severity)                                    \
+  LAZY_STREAM(LOG_ERRNO_STREAM(severity), DLOG_IS_ON(severity))
+#endif
+
+#define DPLOG(severity)                                         \
+  LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity))
+
+#define DVLOG(verboselevel) DLOG_IF(INFO, VLOG_IS_ON(verboselevel))
+
+#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, VLOG_IS_ON(verboselevel))
+
+// Definitions for DCHECK et al.
+
+#if ENABLE_DCHECK
+
+#if defined(NDEBUG)
+
+#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
+  COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_ERROR_REPORT
+const LogSeverity LOG_DCHECK = LOG_ERROR_REPORT;
+BASE_EXPORT extern DcheckState g_dcheck_state;
+#define DCHECK_IS_ON()                                                  \
+  ((::logging::g_dcheck_state ==                                        \
+    ::logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS) &&        \
+   LOG_IS_ON(DCHECK))
+
+#else  // defined(NDEBUG)
+
+// On a regular debug build, we want to have DCHECKs enabled.
+#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
+  COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL
+const LogSeverity LOG_DCHECK = LOG_FATAL;
+#define DCHECK_IS_ON() true
+
+#endif  // defined(NDEBUG)
+
+#else  // ENABLE_DCHECK
+
+// These are just dummy values since DCHECK_IS_ON() is always false in
+// this case.
+#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
+  COMPACT_GOOGLE_LOG_EX_INFO(ClassName , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO
+const LogSeverity LOG_DCHECK = LOG_INFO;
+#define DCHECK_IS_ON() false
+
+#endif  // ENABLE_DCHECK
+#undef ENABLE_DCHECK
+
+// DCHECK et al. make sure to reference |condition| regardless of
+// whether DCHECKs are enabled; this is so that we don't get unused
+// variable warnings if the only use of a variable is in a DCHECK.
+// This behavior is different from DLOG_IF et al.
+
+#define DCHECK(condition)                                           \
+  LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON() && !(condition))   \
+  << "Check failed: " #condition ". "
+
+#define DPCHECK(condition)                                          \
+  LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON() && !(condition))  \
+  << "Check failed: " #condition ". "
+
+// Helper macro for binary operators.
+// Don't use this macro directly in your code, use DCHECK_EQ et al below.
+#define DCHECK_OP(name, op, val1, val2)                         \
+  if (DCHECK_IS_ON())                                           \
+    if (std::string* _result =                                  \
+        logging::Check##name##Impl((val1), (val2),              \
+                                   #val1 " " #op " " #val2))    \
+      logging::LogMessage(                                      \
+          __FILE__, __LINE__, ::logging::LOG_DCHECK,            \
+          _result).stream()
+
+// Equality/Inequality checks - compare two values, and log a
+// LOG_DCHECK message including the two values when the result is not
+// as expected.  The values must have operator<<(ostream, ...)
+// defined.
+//
+// You may append to the error message like so:
+//   DCHECK_NE(1, 2) << ": The world must be ending!";
+//
+// We are very careful to ensure that each argument is evaluated exactly
+// once, and that anything which is legal to pass as a function argument is
+// legal here.  In particular, the arguments may be temporary expressions
+// which will end up being destroyed at the end of the apparent statement,
+// for example:
+//   DCHECK_EQ(string("abc")[1], 'b');
+//
+// WARNING: These may not compile correctly if one of the arguments is a pointer
+// and the other is NULL. To work around this, simply static_cast NULL to the
+// type of the desired pointer.
+
+#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2)
+#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2)
+#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2)
+#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2)
+#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
+#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
+
+#if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD)
+// TODO(port): fix once "enough" works
+#define NOTREACHED() LOG(ERROR) <<  "NOTREACHED()"
+#else
+#define NOTREACHED() DCHECK(false)
+#endif
+
+// Redefine the standard assert to use our nice log files
+#undef assert
+#define assert(x) DLOG_ASSERT(x)
+
+// This class more or less represents a particular log message.  You
+// create an instance of LogMessage and then stream stuff to it.
+// When you finish streaming to it, ~LogMessage is called and the
+// full message gets streamed to the appropriate destination.
+//
+// You shouldn't actually use LogMessage's constructor to log things,
+// though.  You should use the LOG() macro (and variants thereof)
+// above.
+class BASE_EXPORT LogMessage {
+ public:
+  LogMessage(const char* file, int line, LogSeverity severity, int ctr);
+
+  // Two special constructors that generate reduced amounts of code at
+  // LOG call sites for common cases.
+  //
+  // Used for LOG(INFO): Implied are:
+  // severity = LOG_INFO, ctr = 0
+  //
+  // Using this constructor instead of the more complex constructor above
+  // saves a couple of bytes per call site.
+  LogMessage(const char* file, int line);
+
+  // Used for LOG(severity) where severity != INFO.  Implied
+  // are: ctr = 0
+  //
+  // Using this constructor instead of the more complex constructor above
+  // saves a couple of bytes per call site.
+  LogMessage(const char* file, int line, LogSeverity severity);
+
+  // A special constructor used for check failures.  Takes ownership
+  // of the given string.
+  // Implied severity = LOG_FATAL
+  LogMessage(const char* file, int line, std::string* result);
+
+  // A special constructor used for check failures, with the option to
+  // specify severity.  Takes ownership of the given string.
+  LogMessage(const char* file, int line, LogSeverity severity,
+             std::string* result);
+
+  ~LogMessage();
+
+  std::ostream& stream() { return stream_; }
+
+ private:
+  void Init(const char* file, int line);
+
+  LogSeverity severity_;
+  std::ostringstream stream_;
+  size_t message_start_;  // Offset of the start of the message (past prefix
+                          // info).
+  // The file and line information passed in to the constructor.
+  const char* file_;
+  const int line_;
+
+#if defined(OS_WIN)
+  // Stores the current value of GetLastError in the constructor and restores
+  // it in the destructor by calling SetLastError.
+  // This is useful since the LogMessage class uses a lot of Win32 calls
+  // that will lose the value of GLE and the code that called the log function
+  // will have lost the thread error value when the log call returns.
+  class SaveLastError {
+   public:
+    SaveLastError();
+    ~SaveLastError();
+
+    unsigned long get_error() const { return last_error_; }
+
+   protected:
+    unsigned long last_error_;
+  };
+
+  SaveLastError last_error_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(LogMessage);
+};
+
+// A non-macro interface to the log facility; (useful
+// when the logging level is not a compile-time constant).
+inline void LogAtLevel(int const log_level, std::string const &msg) {
+  LogMessage(__FILE__, __LINE__, log_level).stream() << 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 {
+ public:
+  LogMessageVoidify() { }
+  // This has to be an operator with a precedence lower than << but
+  // higher than ?:
+  void operator&(std::ostream&) { }
+};
+
+#if defined(OS_WIN)
+typedef unsigned long SystemErrorCode;
+#elif defined(OS_POSIX)
+typedef int SystemErrorCode;
+#endif
+
+// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to
+// pull in windows.h just for GetLastError() and DWORD.
+BASE_EXPORT SystemErrorCode GetLastSystemErrorCode();
+
+#if defined(OS_WIN)
+// Appends a formatted system message of the GetLastError() type.
+class BASE_EXPORT Win32ErrorLogMessage {
+ public:
+  Win32ErrorLogMessage(const char* file,
+                       int line,
+                       LogSeverity severity,
+                       SystemErrorCode err,
+                       const char* module);
+
+  Win32ErrorLogMessage(const char* file,
+                       int line,
+                       LogSeverity severity,
+                       SystemErrorCode err);
+
+  // Appends the error message before destructing the encapsulated class.
+  ~Win32ErrorLogMessage();
+
+  std::ostream& stream() { return log_message_.stream(); }
+
+ private:
+  SystemErrorCode err_;
+  // Optional name of the module defining the error.
+  const char* module_;
+  LogMessage log_message_;
+
+  DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage);
+};
+#elif defined(OS_POSIX)
+// Appends a formatted system message of the errno type
+class BASE_EXPORT ErrnoLogMessage {
+ public:
+  ErrnoLogMessage(const char* file,
+                  int line,
+                  LogSeverity severity,
+                  SystemErrorCode err);
+
+  // Appends the error message before destructing the encapsulated class.
+  ~ErrnoLogMessage();
+
+  std::ostream& stream() { return log_message_.stream(); }
+
+ private:
+  SystemErrorCode err_;
+  LogMessage log_message_;
+
+  DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage);
+};
+#endif  // OS_WIN
+
+// Closes the log file explicitly if open.
+// 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.
+BASE_EXPORT void CloseLogFile();
+
+// Async signal safe logging mechanism.
+BASE_EXPORT void RawLog(int level, const char* message);
+
+#define RAW_LOG(level, message) logging::RawLog(logging::LOG_ ## level, message)
+
+#define RAW_CHECK(condition)                                                   \
+  do {                                                                         \
+    if (!(condition))                                                          \
+      logging::RawLog(logging::LOG_FATAL, "Check failed: " #condition "\n");   \
+  } while (0)
+
+}  // namespace logging
+
+// These functions are provided as a convenience for logging, which is where we
+// use streams (it is against Google style to use streams in other places). It
+// is designed to allow you to emit non-ASCII Unicode strings to the log file,
+// 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.
+BASE_EXPORT 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();
+}
+
+// The NOTIMPLEMENTED() macro annotates codepaths which have
+// not been implemented yet.
+//
+// The implementation of this macro is controlled by NOTIMPLEMENTED_POLICY:
+//   0 -- Do nothing (stripped by compiler)
+//   1 -- Warn at compile time
+//   2 -- Fail at compile time
+//   3 -- Fail at runtime (DCHECK)
+//   4 -- [default] LOG(ERROR) at runtime
+//   5 -- LOG(ERROR) at runtime, only once per call-site
+
+#ifndef NOTIMPLEMENTED_POLICY
+// Select default policy: LOG(ERROR)
+#define NOTIMPLEMENTED_POLICY 4
+#endif
+
+#if defined(COMPILER_GCC)
+// On Linux, with GCC, we can use __PRETTY_FUNCTION__ to get the demangled name
+// of the current function in the NOTIMPLEMENTED message.
+#define NOTIMPLEMENTED_MSG "Not implemented reached in " << __PRETTY_FUNCTION__
+#else
+#define NOTIMPLEMENTED_MSG "NOT IMPLEMENTED"
+#endif
+
+#if NOTIMPLEMENTED_POLICY == 0
+#define NOTIMPLEMENTED() ;
+#elif NOTIMPLEMENTED_POLICY == 1
+// TODO, figure out how to generate a warning
+#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
+#elif NOTIMPLEMENTED_POLICY == 2
+#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
+#elif NOTIMPLEMENTED_POLICY == 3
+#define NOTIMPLEMENTED() NOTREACHED()
+#elif NOTIMPLEMENTED_POLICY == 4
+#define NOTIMPLEMENTED() LOG(ERROR) << NOTIMPLEMENTED_MSG
+#elif NOTIMPLEMENTED_POLICY == 5
+#define NOTIMPLEMENTED() do {\
+  static int count = 0;\
+  LOG_IF(ERROR, 0 == count++) << NOTIMPLEMENTED_MSG;\
+} while(0)
+#endif
+
+namespace base {
+
+class StringPiece;
+
+// Allows StringPiece to be logged.
+BASE_EXPORT std::ostream& operator<<(std::ostream& o, const StringPiece& piece);
+
+}  // namespace base
+
+#endif  // BASE_LOGGING_H_
diff --git a/base/memory/ref_counted.cc b/base/memory/ref_counted.cc
new file mode 100644 (file)
index 0000000..31ad509
--- /dev/null
@@ -0,0 +1,95 @@
+// 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 "base/logging.h"
+#include "base/threading/thread_collision_warner.h"
+
+namespace base {
+
+namespace subtle {
+
+RefCountedBase::RefCountedBase()
+    : ref_count_(0)
+#ifndef NDEBUG
+    , in_dtor_(false)
+#endif
+    {
+}
+
+RefCountedBase::~RefCountedBase() {
+#ifndef NDEBUG
+  DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
+#endif
+}
+
+void RefCountedBase::AddRef() const {
+  // TODO(maruel): Add back once it doesn't assert 500 times/sec.
+  // Current thread books the critical section "AddRelease" without release it.
+  // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
+#ifndef NDEBUG
+  DCHECK(!in_dtor_);
+#endif
+  ++ref_count_;
+}
+
+bool RefCountedBase::Release() const {
+  // TODO(maruel): Add back once it doesn't assert 500 times/sec.
+  // Current thread books the critical section "AddRelease" without release it.
+  // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
+#ifndef NDEBUG
+  DCHECK(!in_dtor_);
+#endif
+  if (--ref_count_ == 0) {
+#ifndef NDEBUG
+    in_dtor_ = true;
+#endif
+    return true;
+  }
+  return false;
+}
+
+bool RefCountedThreadSafeBase::HasOneRef() const {
+  return AtomicRefCountIsOne(
+      &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_);
+}
+
+RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) {
+#ifndef NDEBUG
+  in_dtor_ = false;
+#endif
+}
+
+RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
+#ifndef NDEBUG
+  DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
+                      "calling Release()";
+#endif
+}
+
+void RefCountedThreadSafeBase::AddRef() const {
+#ifndef NDEBUG
+  DCHECK(!in_dtor_);
+#endif
+  AtomicRefCountInc(&ref_count_);
+}
+
+bool RefCountedThreadSafeBase::Release() const {
+#ifndef NDEBUG
+  DCHECK(!in_dtor_);
+  DCHECK(!AtomicRefCountIsZero(&ref_count_));
+#endif
+  if (!AtomicRefCountDec(&ref_count_)) {
+#ifndef NDEBUG
+    in_dtor_ = true;
+#endif
+    return true;
+  }
+  return false;
+}
+
+}  // namespace subtle
+
+}  // namespace base
diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
new file mode 100644 (file)
index 0000000..439fda4
--- /dev/null
@@ -0,0 +1,299 @@
+// 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_MEMORY_REF_COUNTED_H_
+#define BASE_MEMORY_REF_COUNTED_H_
+#pragma once
+
+#include "base/atomic_ref_count.h"
+#include "base/base_export.h"
+#include "base/threading/thread_collision_warner.h"
+
+namespace base {
+
+namespace subtle {
+
+class BASE_EXPORT RefCountedBase {
+ public:
+  static bool ImplementsThreadSafeReferenceCounting() { return false; }
+
+  bool HasOneRef() const { return ref_count_ == 1; }
+
+ protected:
+  RefCountedBase();
+  ~RefCountedBase();
+
+  void AddRef() const;
+
+  // Returns true if the object should self-delete.
+  bool Release() const;
+
+ private:
+  mutable int ref_count_;
+#ifndef NDEBUG
+  mutable bool in_dtor_;
+#endif
+
+  DFAKE_MUTEX(add_release_);
+
+  DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
+};
+
+class BASE_EXPORT RefCountedThreadSafeBase {
+ public:
+  static bool ImplementsThreadSafeReferenceCounting() { return true; }
+
+  bool HasOneRef() const;
+
+ protected:
+  RefCountedThreadSafeBase();
+  ~RefCountedThreadSafeBase();
+
+  void AddRef() const;
+
+  // Returns true if the object should self-delete.
+  bool Release() const;
+
+ private:
+  mutable AtomicRefCount ref_count_;
+#ifndef NDEBUG
+  mutable bool in_dtor_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
+};
+
+}  // namespace subtle
+
+//
+// A base class for reference counted classes.  Otherwise, known as a cheap
+// knock-off of WebKit's RefCounted<T> class.  To use this guy just extend your
+// class from it like so:
+//
+//   class MyFoo : public base::RefCounted<MyFoo> {
+//    ...
+//    private:
+//     friend class base::RefCounted<MyFoo>;
+//     ~MyFoo();
+//   };
+//
+// You should always make your destructor private, to avoid any code deleting
+// the object accidently while there are references to it.
+template <class T>
+class RefCounted : public subtle::RefCountedBase {
+ public:
+  RefCounted() { }
+  ~RefCounted() { }
+
+  void AddRef() const {
+    subtle::RefCountedBase::AddRef();
+  }
+
+  void Release() const {
+    if (subtle::RefCountedBase::Release()) {
+      delete static_cast<const T*>(this);
+    }
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
+};
+
+// Forward declaration.
+template <class T, typename Traits> class RefCountedThreadSafe;
+
+// Default traits for RefCountedThreadSafe<T>.  Deletes the object when its ref
+// count reaches 0.  Overload to delete it on a different thread etc.
+template<typename T>
+struct DefaultRefCountedThreadSafeTraits {
+  static void Destruct(const T* x) {
+    // Delete through RefCountedThreadSafe to make child classes only need to be
+    // friend with RefCountedThreadSafe instead of this struct, which is an
+    // implementation detail.
+    RefCountedThreadSafe<T,
+                         DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
+  }
+};
+
+//
+// A thread-safe variant of RefCounted<T>
+//
+//   class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
+//    ...
+//   };
+//
+// If you're using the default trait, then you should add compile time
+// asserts that no one else is deleting your object.  i.e.
+//    private:
+//     friend class base::RefCountedThreadSafe<MyFoo>;
+//     ~MyFoo();
+template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
+class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
+ public:
+  RefCountedThreadSafe() { }
+  ~RefCountedThreadSafe() { }
+
+  void AddRef() const {
+    subtle::RefCountedThreadSafeBase::AddRef();
+  }
+
+  void Release() const {
+    if (subtle::RefCountedThreadSafeBase::Release()) {
+      Traits::Destruct(static_cast<const T*>(this));
+    }
+  }
+
+ private:
+  friend struct DefaultRefCountedThreadSafeTraits<T>;
+  static void DeleteInternal(const T* x) { delete x; }
+
+  DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
+};
+
+//
+// A wrapper for some piece of data so we can place other things in
+// scoped_refptrs<>.
+//
+template<typename T>
+class RefCountedData : public base::RefCounted< base::RefCountedData<T> > {
+ public:
+  RefCountedData() : data() {}
+  RefCountedData(const T& in_value) : data(in_value) {}
+
+  T data;
+};
+
+}  // namespace base
+
+//
+// A smart pointer class for reference counted objects.  Use this class instead
+// of calling AddRef and Release manually on a reference counted object to
+// avoid common memory leaks caused by forgetting to Release an object
+// reference.  Sample usage:
+//
+//   class MyFoo : public RefCounted<MyFoo> {
+//    ...
+//   };
+//
+//   void some_function() {
+//     scoped_refptr<MyFoo> foo = new MyFoo();
+//     foo->Method(param);
+//     // |foo| is released when this function returns
+//   }
+//
+//   void some_other_function() {
+//     scoped_refptr<MyFoo> foo = new MyFoo();
+//     ...
+//     foo = NULL;  // explicitly releases |foo|
+//     ...
+//     if (foo)
+//       foo->Method(param);
+//   }
+//
+// The above examples show how scoped_refptr<T> acts like a pointer to T.
+// Given two scoped_refptr<T> classes, it is also possible to exchange
+// references between the two objects, like so:
+//
+//   {
+//     scoped_refptr<MyFoo> a = new MyFoo();
+//     scoped_refptr<MyFoo> b;
+//
+//     b.swap(a);
+//     // now, |b| references the MyFoo object, and |a| references NULL.
+//   }
+//
+// To make both |a| and |b| in the above example reference the same MyFoo
+// object, simply use the assignment operator:
+//
+//   {
+//     scoped_refptr<MyFoo> a = new MyFoo();
+//     scoped_refptr<MyFoo> b;
+//
+//     b = a;
+//     // now, |a| and |b| each own a reference to the same MyFoo object.
+//   }
+//
+template <class T>
+class scoped_refptr {
+ public:
+  scoped_refptr() : ptr_(NULL) {
+  }
+
+  scoped_refptr(T* p) : ptr_(p) {
+    if (ptr_)
+      ptr_->AddRef();
+  }
+
+  scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
+    if (ptr_)
+      ptr_->AddRef();
+  }
+
+  template <typename U>
+  scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
+    if (ptr_)
+      ptr_->AddRef();
+  }
+
+  ~scoped_refptr() {
+    if (ptr_)
+      ptr_->Release();
+  }
+
+  T* get() const { return ptr_; }
+  operator T*() const { return ptr_; }
+  T* operator->() const { return ptr_; }
+
+  // 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.
+  T* release() {
+    T* retVal = ptr_;
+    ptr_ = NULL;
+    return retVal;
+  }
+
+  scoped_refptr<T>& operator=(T* p) {
+    // AddRef first so that self assignment should work
+    if (p)
+      p->AddRef();
+    if (ptr_ )
+      ptr_ ->Release();
+    ptr_ = p;
+    return *this;
+  }
+
+  scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
+    return *this = r.ptr_;
+  }
+
+  template <typename U>
+  scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
+    return *this = r.get();
+  }
+
+  void swap(T** pp) {
+    T* p = ptr_;
+    ptr_ = *pp;
+    *pp = p;
+  }
+
+  void swap(scoped_refptr<T>& r) {
+    swap(&r.ptr_);
+  }
+
+ protected:
+  T* ptr_;
+};
+
+// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
+// having to retype all the template arguments
+template <typename T>
+scoped_refptr<T> make_scoped_refptr(T* t) {
+  return scoped_refptr<T>(t);
+}
+
+#endif  // BASE_MEMORY_REF_COUNTED_H_
diff --git a/base/memory/ref_counted_memory.cc b/base/memory/ref_counted_memory.cc
new file mode 100644 (file)
index 0000000..7e034f9
--- /dev/null
@@ -0,0 +1,72 @@
+// 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_memory.h"
+
+#include "base/logging.h"
+
+RefCountedMemory::RefCountedMemory() {
+}
+
+RefCountedMemory::~RefCountedMemory() {
+}
+
+const unsigned char* RefCountedStaticMemory::front() const {
+  return data_;
+}
+
+size_t RefCountedStaticMemory::size() const {
+  return length_;
+}
+
+RefCountedBytes::RefCountedBytes() {
+}
+
+RefCountedBytes::RefCountedBytes(const std::vector<unsigned char>& initializer)
+    : data_(initializer) {
+}
+
+RefCountedBytes* RefCountedBytes::TakeVector(
+    std::vector<unsigned char>* to_destroy) {
+  RefCountedBytes* bytes = new RefCountedBytes;
+  bytes->data_.swap(*to_destroy);
+  return bytes;
+}
+
+const unsigned char* RefCountedBytes::front() const {
+  // STL will assert if we do front() on an empty vector, but calling code
+  // expects a NULL.
+  return size() ? &data_.front() : NULL;
+}
+
+size_t RefCountedBytes::size() const {
+  return data_.size();
+}
+
+RefCountedBytes::~RefCountedBytes() {
+}
+
+namespace base {
+
+RefCountedString::RefCountedString() {}
+
+RefCountedString::~RefCountedString() {}
+
+// static
+RefCountedString* RefCountedString::TakeString(std::string* to_destroy) {
+  RefCountedString* self = new RefCountedString;
+  to_destroy->swap(self->data_);
+  return self;
+}
+
+const unsigned char* RefCountedString::front() const {
+  return data_.empty() ? NULL :
+         reinterpret_cast<const unsigned char*>(data_.data());
+}
+
+size_t RefCountedString::size() const {
+  return data_.size();
+}
+
+}  //  namespace base
diff --git a/base/memory/ref_counted_memory.h b/base/memory/ref_counted_memory.h
new file mode 100644 (file)
index 0000000..7b55d14
--- /dev/null
@@ -0,0 +1,119 @@
+// 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_MEMORY_REF_COUNTED_MEMORY_H_
+#define BASE_MEMORY_REF_COUNTED_MEMORY_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/compiler_specific.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.
+
+// 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 BASE_EXPORT 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.
+  virtual const unsigned char* front() const = 0;
+
+  // Size of the memory pointed to.
+  virtual size_t size() const = 0;
+
+ protected:
+  friend class base::RefCountedThreadSafe<RefCountedMemory>;
+  RefCountedMemory();
+  virtual ~RefCountedMemory();
+};
+
+// An implementation of RefCountedMemory, where the ref counting does not
+// matter.
+class BASE_EXPORT RefCountedStaticMemory : public RefCountedMemory {
+ public:
+  RefCountedStaticMemory()
+      : data_(NULL), length_(0) {}
+  RefCountedStaticMemory(const unsigned char* data, size_t length)
+      : data_(length ? data : NULL), length_(length) {}
+
+  // Overridden from RefCountedMemory:
+  virtual const unsigned char* front() const OVERRIDE;
+  virtual size_t size() const OVERRIDE;
+
+ private:
+  const unsigned char* data_;
+  size_t length_;
+
+  DISALLOW_COPY_AND_ASSIGN(RefCountedStaticMemory);
+};
+
+// An implementation of RefCountedMemory, where we own our the data in a
+// vector.
+class BASE_EXPORT RefCountedBytes : public RefCountedMemory {
+ public:
+  RefCountedBytes();
+
+  // Constructs a RefCountedBytes object by _copying_ from |initializer|.
+  RefCountedBytes(const std::vector<unsigned char>& initializer);
+
+  // Constructs a RefCountedBytes object by performing a swap. (To non
+  // destructively build a RefCountedBytes, use the constructor that takes a
+  // vector.)
+  static RefCountedBytes* TakeVector(std::vector<unsigned char>* to_destroy);
+
+  // Overridden from RefCountedMemory:
+  virtual const unsigned char* front() const OVERRIDE;
+  virtual size_t size() const OVERRIDE;
+
+  const std::vector<unsigned char>& data() const { return data_; }
+  std::vector<unsigned char>& data() { return data_; }
+
+ private:
+  friend class base::RefCountedThreadSafe<RefCountedBytes>;
+  virtual ~RefCountedBytes();
+
+  std::vector<unsigned char> data_;
+
+  DISALLOW_COPY_AND_ASSIGN(RefCountedBytes);
+};
+
+namespace base {
+
+// An implementation of RefCountedMemory, where the bytes are stored in an STL
+// string. Use this if your data naturally arrives in that format.
+class BASE_EXPORT RefCountedString : public RefCountedMemory {
+ public:
+  RefCountedString();
+
+  // Constructs a RefCountedString object by performing a swap. (To non
+  // destructively build a RefCountedString, use the default constructor and
+  // copy into object->data()).
+  static RefCountedString* TakeString(std::string* to_destroy);
+
+  // Overridden from RefCountedMemory:
+  virtual const unsigned char* front() const OVERRIDE;
+  virtual size_t size() const OVERRIDE;
+
+  const std::string& data() const { return data_; }
+  std::string& data() { return data_; }
+
+ private:
+  friend class base::RefCountedThreadSafe<RefCountedString>;
+  virtual ~RefCountedString();
+
+  std::string data_;
+
+  DISALLOW_COPY_AND_ASSIGN(RefCountedString);
+};
+
+}  // namespace base
+
+#endif  // BASE_MEMORY_REF_COUNTED_MEMORY_H_
diff --git a/base/memory/ref_counted_memory_unittest.cc b/base/memory/ref_counted_memory_unittest.cc
new file mode 100644 (file)
index 0000000..1936040
--- /dev/null
@@ -0,0 +1,45 @@
+// 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_memory.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+TEST(RefCountedMemoryUnitTest, RefCountedStaticMemory) {
+  scoped_refptr<RefCountedMemory> mem = new RefCountedStaticMemory(
+      reinterpret_cast<const uint8*>("static mem00"), 10);
+
+  EXPECT_EQ(10U, mem->size());
+  EXPECT_EQ("static mem",
+            std::string(reinterpret_cast<const char*>(mem->front()),
+                        mem->size()));
+}
+
+TEST(RefCountedMemoryUnitTest, RefCountedBytes) {
+  std::vector<uint8> data;
+  data.push_back(45);
+  data.push_back(99);
+  scoped_refptr<RefCountedMemory> mem = RefCountedBytes::TakeVector(&data);
+
+  EXPECT_EQ(0U, data.size());
+
+  EXPECT_EQ(2U, mem->size());
+  EXPECT_EQ(45U, mem->front()[0]);
+  EXPECT_EQ(99U, mem->front()[1]);
+}
+
+TEST(RefCountedMemoryUnitTest, RefCountedString) {
+  std::string s("destroy me");
+  scoped_refptr<RefCountedMemory> mem = RefCountedString::TakeString(&s);
+
+  EXPECT_EQ(0U, s.size());
+
+  EXPECT_EQ(10U, mem->size());
+  EXPECT_EQ('d', mem->front()[0]);
+  EXPECT_EQ('e', mem->front()[1]);
+}
+
+}  //  namespace base
diff --git a/base/memory/ref_counted_unittest.cc b/base/memory/ref_counted_unittest.cc
new file mode 100644 (file)
index 0000000..dcc292f
--- /dev/null
@@ -0,0 +1,36 @@
+// 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"
+
+namespace {
+
+class SelfAssign : public base::RefCounted<SelfAssign> {
+  friend class base::RefCounted<SelfAssign>;
+
+  ~SelfAssign() {}
+};
+
+class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
+ public:
+  CheckDerivedMemberAccess() {
+    // This shouldn't compile if we don't have access to the member variable.
+    SelfAssign** pptr = &ptr_;
+    EXPECT_EQ(*pptr, ptr_);
+  }
+};
+
+}  // end namespace
+
+TEST(RefCountedUnitTest, TestSelfAssignment) {
+  SelfAssign* p = new SelfAssign;
+  scoped_refptr<SelfAssign> var(p);
+  var = var;
+  EXPECT_EQ(var.get(), p);
+}
+
+TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
+  CheckDerivedMemberAccess check;
+}
diff --git a/base/pickle.cc b/base/pickle.cc
new file mode 100644 (file)
index 0000000..f42f249
--- /dev/null
@@ -0,0 +1,449 @@
+// 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/pickle.h"
+
+#include <stdlib.h>
+
+#include <algorithm>  // for max()
+#include <limits>
+
+//------------------------------------------------------------------------------
+
+// static
+const int Pickle::kPayloadUnit = 64;
+
+// We mark a read only pickle with a special capacity_.
+static const size_t kCapacityReadOnly = std::numeric_limits<size_t>::max();
+
+// Payload is uint32 aligned.
+
+Pickle::Pickle()
+    : header_(NULL),
+      header_size_(sizeof(Header)),
+      capacity_(0),
+      variable_buffer_offset_(0) {
+  Resize(kPayloadUnit);
+  header_->payload_size = 0;
+}
+
+Pickle::Pickle(int header_size)
+    : header_(NULL),
+      header_size_(AlignInt(header_size, sizeof(uint32))),
+      capacity_(0),
+      variable_buffer_offset_(0) {
+  DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header));
+  DCHECK_LE(header_size, kPayloadUnit);
+  Resize(kPayloadUnit);
+  header_->payload_size = 0;
+}
+
+Pickle::Pickle(const char* data, int data_len)
+    : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
+      header_size_(0),
+      capacity_(kCapacityReadOnly),
+      variable_buffer_offset_(0) 
+{
+
+  if (data_len >= static_cast<int>(sizeof(Header)))
+       {
+       header_size_ = data_len - header_->payload_size;
+       }
+
+  if (header_size_ > static_cast<unsigned int>(data_len))
+       {       
+    header_size_ = 0;
+       }
+
+
+  if (header_size_ != AlignInt(header_size_, sizeof(uint32)))
+       {
+    header_size_ = 0;
+       }
+
+
+  // If there is anything wrong with the data, we're not going to use it.
+  if (!header_size_)
+    header_ = NULL;
+}
+
+Pickle::Pickle(const Pickle& other)
+    : header_(NULL),
+      header_size_(other.header_size_),
+      capacity_(0),
+      variable_buffer_offset_(other.variable_buffer_offset_) {
+  size_t payload_size = header_size_ + other.header_->payload_size;
+  bool resized = Resize(payload_size);
+  CHECK(resized);  // Realloc failed.
+  memcpy(header_, other.header_, payload_size);
+}
+
+Pickle::~Pickle() {
+  if (capacity_ != kCapacityReadOnly)
+    free(header_);
+}
+
+Pickle& Pickle::operator=(const Pickle& other) {
+  if (this == &other) {
+    NOTREACHED();
+    return *this;
+  }
+  if (capacity_ == kCapacityReadOnly) {
+    header_ = NULL;
+    capacity_ = 0;
+  }
+  if (header_size_ != other.header_size_) {
+    free(header_);
+    header_ = NULL;
+    header_size_ = other.header_size_;
+  }
+  bool resized = Resize(other.header_size_ + other.header_->payload_size);
+  CHECK(resized);  // Realloc failed.
+  memcpy(header_, other.header_,
+         other.header_size_ + other.header_->payload_size);
+  variable_buffer_offset_ = other.variable_buffer_offset_;
+  return *this;
+}
+
+bool Pickle::ReadBool(void** iter, bool* result) const {
+  DCHECK(iter);
+
+  int tmp;
+  if (!ReadInt(iter, &tmp))
+    return false;
+  DCHECK(0 == tmp || 1 == tmp);
+  *result = tmp ? true : false;
+  return true;
+}
+
+bool Pickle::ReadInt(void** iter, int* result) const {
+  DCHECK(iter);
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+    return false;
+
+  // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not
+  // dependent on alignment.
+  // Next line is otherwise the same as: memcpy(result, *iter, sizeof(*result));
+  *result = *reinterpret_cast<int*>(*iter);
+
+  UpdateIter(iter, sizeof(*result));
+  return true;
+}
+
+bool Pickle::ReadLong(void** iter, long* result) const {
+  DCHECK(iter);
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+    return false;
+
+  // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not
+  // dependent on alignment.
+  memcpy(result, *iter, sizeof(*result));
+
+  UpdateIter(iter, sizeof(*result));
+  return true;
+}
+
+bool Pickle::ReadSize(void** iter, size_t* result) const {
+  DCHECK(iter);
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+    return false;
+
+  // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not
+  // dependent on alignment.
+  // Next line is otherwise the same as: memcpy(result, *iter, sizeof(*result));
+  *result = *reinterpret_cast<size_t*>(*iter);
+
+  UpdateIter(iter, sizeof(*result));
+  return true;
+}
+
+bool Pickle::ReadUInt16(void** iter, uint16* result) const {
+  DCHECK(iter);
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+    return false;
+
+  memcpy(result, *iter, sizeof(*result));
+
+  UpdateIter(iter, sizeof(*result));
+  return true;
+}
+
+bool Pickle::ReadUInt32(void** iter, uint32* result) const {
+  DCHECK(iter);
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+    return false;
+
+  memcpy(result, *iter, sizeof(*result));
+
+  UpdateIter(iter, sizeof(*result));
+  return true;
+}
+
+bool Pickle::ReadInt64(void** iter, int64* result) const {
+  DCHECK(iter);
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+    return false;
+
+  memcpy(result, *iter, sizeof(*result));
+
+  UpdateIter(iter, sizeof(*result));
+  return true;
+}
+
+bool Pickle::ReadUInt64(void** iter, uint64* result) const {
+  DCHECK(iter);
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+    return false;
+
+  memcpy(result, *iter, sizeof(*result));
+
+  UpdateIter(iter, sizeof(*result));
+  return true;
+}
+
+
+bool Pickle::ReadString(void** iter, std::string* result) const {
+  DCHECK(iter);
+
+  int len;
+  if (!ReadLength(iter, &len))
+    return false;
+  if (!IteratorHasRoomFor(*iter, len))
+    return false;
+
+  char* chars = reinterpret_cast<char*>(*iter);
+  result->assign(chars, len);
+
+  UpdateIter(iter, len);
+  return true;
+}
+
+/*
+bool Pickle::ReadWString(void** iter, std::wstring* result) const {
+  DCHECK(iter);
+
+  int len;
+  if (!ReadLength(iter, &len))
+    return false;
+  // Avoid integer overflow.
+  if (len > INT_MAX / static_cast<int>(sizeof(wchar_t)))
+    return false;
+  if (!IteratorHasRoomFor(*iter, len * sizeof(wchar_t)))
+    return false;
+
+  wchar_t* chars = reinterpret_cast<wchar_t*>(*iter);
+  result->assign(chars, len);
+
+  UpdateIter(iter, len * sizeof(wchar_t));
+  return true;
+}
+
+bool Pickle::ReadString16(void** iter, string16* result) const {
+  DCHECK(iter);
+
+  int len;
+  if (!ReadLength(iter, &len))
+    return false;
+  if (!IteratorHasRoomFor(*iter, len * sizeof(char16)))
+    return false;
+
+  char16* chars = reinterpret_cast<char16*>(*iter);
+  result->assign(chars, len);
+
+  UpdateIter(iter, len * sizeof(char16));
+  return true;
+}
+*/
+
+bool Pickle::ReadData(void** iter, const char** data, int* length) const {
+  DCHECK(iter);
+  DCHECK(data);
+  DCHECK(length);
+  *length = 0;
+  *data = 0;
+
+  if (!ReadLength(iter, length))
+    return false;
+
+  return ReadBytes(iter, data, *length);
+}
+
+bool Pickle::ReadBytes(void** iter, const char** data, int length) const {
+  DCHECK(iter);
+  DCHECK(data);
+  *data = 0;
+  if (!*iter)
+    *iter = const_cast<char*>(payload());
+
+  if (!IteratorHasRoomFor(*iter, length))
+    return false;
+
+  *data = reinterpret_cast<const char*>(*iter);
+
+  UpdateIter(iter, length);
+  return true;
+}
+
+bool Pickle::ReadLength(void** iter, int* result) const {
+  if (!ReadInt(iter, result))
+    return false;
+  return ((*result) >= 0);
+}
+
+
+bool Pickle::WriteString(const std::string& value) {
+  if (!WriteInt(static_cast<int>(value.size())))
+    return false;
+
+  return WriteBytes(value.data(), static_cast<int>(value.size()));
+}
+
+/*
+bool Pickle::WriteWString(const std::wstring& value) {
+  if (!WriteInt(static_cast<int>(value.size())))
+    return false;
+
+  return WriteBytes(value.data(),
+                    static_cast<int>(value.size() * sizeof(wchar_t)));
+}
+
+bool Pickle::WriteString16(const string16& value) {
+  if (!WriteInt(static_cast<int>(value.size())))
+    return false;
+
+  return WriteBytes(value.data(),
+                    static_cast<int>(value.size()) * sizeof(char16));
+}
+*/
+
+bool Pickle::WriteData(const char* data, int length) {
+  return length >= 0 && WriteInt(length) && WriteBytes(data, length);
+}
+
+bool Pickle::WriteBytes(const void* data, int data_len) {
+  DCHECK_NE(kCapacityReadOnly, capacity_) << "oops: pickle is readonly";
+
+  char* dest = BeginWrite(data_len);
+  if (!dest)
+    return false;
+
+  memcpy(dest, data, data_len);
+
+  EndWrite(dest, data_len);
+  return true;
+}
+
+char* Pickle::BeginWriteData(int length) {
+  DCHECK_EQ(variable_buffer_offset_, 0U) <<
+    "There can only be one variable buffer in a Pickle";
+
+  if (length < 0 || !WriteInt(length))
+    return NULL;
+
+  char *data_ptr = BeginWrite(length);
+  if (!data_ptr)
+    return NULL;
+
+  variable_buffer_offset_ =
+      data_ptr - reinterpret_cast<char*>(header_) - sizeof(int);
+
+  // EndWrite doesn't necessarily have to be called after the write operation,
+  // so we call it here to pad out what the caller will eventually write.
+  EndWrite(data_ptr, length);
+  return data_ptr;
+}
+
+void Pickle::TrimWriteData(int new_length) {
+  DCHECK_NE(variable_buffer_offset_, 0U);
+
+  // Fetch the the variable buffer size
+  int* cur_length = reinterpret_cast<int*>(
+      reinterpret_cast<char*>(header_) + variable_buffer_offset_);
+
+  if (new_length < 0 || new_length > *cur_length) {
+    NOTREACHED() << "Invalid length in TrimWriteData.";
+    return;
+  }
+
+  // Update the payload size and variable buffer size
+  header_->payload_size -= (*cur_length - new_length);
+  *cur_length = new_length;
+}
+
+char* Pickle::BeginWrite(size_t length) {
+  // write at a uint32-aligned offset from the beginning of the header
+  size_t offset = AlignInt(header_->payload_size, sizeof(uint32));
+
+  size_t new_size = offset + length;
+  size_t needed_size = header_size_ + new_size;
+  if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
+    return NULL;
+
+#ifdef ARCH_CPU_64_BITS
+  DCHECK_LE(length, std::numeric_limits<uint32>::max());
+#endif
+
+  header_->payload_size = static_cast<uint32>(new_size);
+  return payload() + offset;
+}
+
+void Pickle::EndWrite(char* dest, int length) {
+  // Zero-pad to keep tools like purify from complaining about uninitialized
+  // memory.
+  if (length % sizeof(uint32))
+    memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32)));
+}
+
+bool Pickle::Resize(size_t new_capacity) {
+  new_capacity = AlignInt(new_capacity, kPayloadUnit);
+
+  CHECK_NE(capacity_, kCapacityReadOnly);
+  void* p = realloc(header_, new_capacity);
+  if (!p)
+    return false;
+
+  header_ = reinterpret_cast<Header*>(p);
+  capacity_ = new_capacity;
+  return true;
+}
+
+// static
+const char* Pickle::FindNext(size_t header_size,
+                             const char* start,
+                             const char* end) {
+  DCHECK_EQ(header_size, AlignInt(header_size, sizeof(uint32)));
+  DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit));
+
+  if (static_cast<size_t>(end - start) < sizeof(Header))
+    return NULL;
+
+  const Header* hdr = reinterpret_cast<const Header*>(start);
+  const char* payload_base = start + header_size;
+  const char* payload_end = payload_base + hdr->payload_size;
+  if (payload_end < payload_base)
+    return NULL;
+
+  return (payload_end > end) ? NULL : payload_end;
+}
diff --git a/base/pickle.h b/base/pickle.h
new file mode 100644 (file)
index 0000000..e7ececf
--- /dev/null
@@ -0,0 +1,249 @@
+// 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_PICKLE_H__
+#define BASE_PICKLE_H__
+#pragma once
+
+#include <string>
+#include <iostream>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+//#include "base/gtest_prod_util.h" // jaehwa
+//#include "base/logging.h"         // jaehwa
+#include "log.h"                // jaehwa
+//#include "base/string16.h"        // jaehwa
+
+// This class provides facilities for basic binary value packing and unpacking.
+//
+// The Pickle class supports appending primitive values (ints, strings, etc.)
+// to a pickle instance.  The Pickle instance grows its internal memory buffer
+// dynamically to hold the sequence of primitive values.   The internal memory
+// buffer is exposed as the "data" of the Pickle.  This "data" can be passed
+// to a Pickle object to initialize it for reading.
+//
+// When reading from a Pickle object, it is important for the consumer to know
+// what value types to read and in what order to read them as the Pickle does
+// not keep track of the type of data written to it.
+//
+// The Pickle's data has a header which contains the size of the Pickle's
+// payload.  It can optionally support additional space in the header.  That
+// space is controlled by the header_size parameter passed to the Pickle
+// constructor.
+//
+class BASE_EXPORT Pickle {
+ public:
+  // Initialize a Pickle object using the default header size.
+  Pickle();
+
+  // Initialize a Pickle object with the specified header size in bytes, which
+  // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
+  // will be rounded up to ensure that the header size is 32bit-aligned.
+  explicit Pickle(int header_size);
+
+  // Initializes a Pickle from a const block of data.  The data is not copied;
+  // instead the data is merely referenced by this Pickle.  Only const methods
+  // should be used on the Pickle when initialized this way.  The header
+  // padding size is deduced from the data length.
+  Pickle(const char* data, int data_len);
+
+  // Initializes a Pickle as a deep copy of another Pickle.
+  Pickle(const Pickle& other);
+
+  virtual ~Pickle();
+
+  // Performs a deep copy.
+  Pickle& operator=(const Pickle& other);
+
+  // Returns the size of the Pickle's data.
+  size_t size() const { return header_size_ + header_->payload_size; }
+
+  // Returns the data for this Pickle.
+  const void* data() const { return header_; }
+
+  // Methods for reading the payload of the Pickle.  To read from the start of
+  // the Pickle, initialize *iter to NULL.  If successful, these methods return
+  // true.  Otherwise, false is returned to indicate that the result could not
+  // be extracted.
+  bool ReadBool(void** iter, bool* result) const;
+  bool ReadInt(void** iter, int* result) const;
+  bool ReadLong(void** iter, long* result) const;
+  bool ReadSize(void** iter, size_t* result) const;
+  bool ReadUInt16(void** iter, uint16* result) const;
+  bool ReadUInt32(void** iter, uint32* result) const;
+  bool ReadInt64(void** iter, int64* result) const;
+  bool ReadUInt64(void** iter, uint64* result) const;
+  bool ReadString(void** iter, std::string* result) const;
+//  bool ReadWString(void** iter, std::wstring* result) const;
+//  bool ReadString16(void** iter, string16* result) const;
+  bool ReadData(void** iter, const char** data, int* length) const;
+  bool ReadBytes(void** iter, const char** data, int length) const;
+
+  // Safer version of ReadInt() checks for the result not being negative.
+  // Use it for reading the object sizes.
+  bool ReadLength(void** iter, int* result) const;
+
+  // Methods for adding to the payload of the Pickle.  These values are
+  // appended to the end of the Pickle's payload.  When reading values from a
+  // Pickle, it is important to read them in the order in which they were added
+  // to the Pickle.
+  bool WriteBool(bool value) {
+    return WriteInt(value ? 1 : 0);
+  }
+  bool WriteInt(int value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteLong(long value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteSize(size_t value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteUInt16(uint16 value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteUInt32(uint32 value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteInt64(int64 value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteUInt64(uint64 value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteString(const std::string& value);
+//  bool WriteWString(const std::wstring& value);
+//  bool WriteString16(const string16& value);
+    bool WriteData(const char* data, int length);
+    bool WriteBytes(const void* data, int data_len);
+
+  // Same as WriteData, but allows the caller to write directly into the
+  // Pickle. This saves a copy in cases where the data is not already
+  // available in a buffer. The caller should take care to not write more
+  // than the length it declares it will. Use ReadData to get the data.
+  // Returns NULL on failure.
+  //
+  // The returned pointer will only be valid until the next write operation
+  // on this Pickle.
+  char* BeginWriteData(int length);
+
+  // For Pickles which contain variable length buffers (e.g. those created
+  // with BeginWriteData), the Pickle can
+  // be 'trimmed' if the amount of data required is less than originally
+  // requested.  For example, you may have created a buffer with 10K of data,
+  // but decided to only fill 10 bytes of that data.  Use this function
+  // to trim the buffer so that we don't send 9990 bytes of unused data.
+  // You cannot increase the size of the variable buffer; only shrink it.
+  // This function assumes that the length of the variable buffer has
+  // not been changed.
+  void TrimWriteData(int length);
+
+  // Payload follows after allocation of Header (header size is customizable).
+  struct Header {
+    uint32 payload_size;  // Specifies the size of the payload.
+  };
+
+  // Returns the header, cast to a user-specified type T.  The type T must be a
+  // subclass of Header and its size must correspond to the header_size passed
+  // to the Pickle constructor.
+  template <class T>
+  T* headerT() {
+    DCHECK_EQ(header_size_, sizeof(T));
+    return static_cast<T*>(header_);
+  }
+  template <class T>
+  const T* headerT() const {
+    DCHECK_EQ(header_size_, sizeof(T));
+    return static_cast<const T*>(header_);
+  }
+
+  // Returns true if the given iterator could point to data with the given
+  // length. If there is no room for the given data before the end of the
+  // payload, returns false.
+  bool IteratorHasRoomFor(const void* iter, int len) const {
+    if ((len < 0) || (iter < header_) || iter > end_of_payload())
+      return false;
+    const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
+    // Watch out for overflow in pointer calculation, which wraps.
+    return (iter <= end_of_region) && (end_of_region <= end_of_payload());
+  }
+
+ protected:
+  size_t payload_size() const { return header_->payload_size; }
+
+  char* payload() {
+    return reinterpret_cast<char*>(header_) + header_size_;
+  }
+  const char* payload() const {
+    return reinterpret_cast<const char*>(header_) + header_size_;
+  }
+
+  // Returns the address of the byte immediately following the currently valid
+  // header + payload.
+  char* end_of_payload() {
+    // We must have a valid header_.
+    return payload() + payload_size();
+  }
+  const char* end_of_payload() const {
+    // This object may be invalid.
+    return header_ ? payload() + payload_size() : NULL;
+  }
+
+  size_t capacity() const {
+    return capacity_;
+  }
+
+  // Resizes the buffer for use when writing the specified amount of data. The
+  // location that the data should be written at is returned, or NULL if there
+  // was an error. Call EndWrite with the returned offset and the given length
+  // to pad out for the next write.
+  char* BeginWrite(size_t length);
+
+  // Completes the write operation by padding the data with NULL bytes until it
+  // is padded. Should be paired with BeginWrite, but it does not necessarily
+  // have to be called after the data is written.
+  void EndWrite(char* dest, int length);
+
+  // Resize the capacity, note that the input value should include the size of
+  // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
+  // A realloc() failure will cause a Resize failure... and caller should check
+  // the return result for true (i.e., successful resizing).
+  bool Resize(size_t new_capacity);
+
+  // Aligns 'i' by rounding it up to the next multiple of 'alignment'
+  static size_t AlignInt(size_t i, int alignment) {
+    return i + (alignment - (i % alignment)) % alignment;
+  }
+
+  // Moves the iterator by the given number of bytes, making sure it is aligned.
+  // Pointer (iterator) is NOT aligned, but the change in the pointer
+  // is guaranteed to be a multiple of sizeof(uint32).
+  static void UpdateIter(void** iter, int bytes) {
+    *iter = static_cast<char*>(*iter) + AlignInt(bytes, sizeof(uint32));
+  }
+
+  // Find the end of the pickled data that starts at range_start.  Returns NULL
+  // if the entire Pickle is not found in the given data range.
+  static const char* FindNext(size_t header_size,
+                              const char* range_start,
+                              const char* range_end);
+
+  // The allocation granularity of the payload.
+  static const int kPayloadUnit;
+
+ private:
+  Header* header_;
+  size_t header_size_;  // Supports extra data between header and payload.
+  // Allocation size of payload (or -1 if allocation is const).
+  size_t capacity_;
+  size_t variable_buffer_offset_;  // IF non-zero, then offset to a buffer.
+
+//  FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
+//  FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
+//  FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
+//  FRIEND_TEST_ALL_PREFIXES(PickleTest, IteratorHasRoom);
+};
+
+#endif  // BASE_PICKLE_H__
diff --git a/base/platform_file_posix.cc b/base/platform_file_posix.cc
new file mode 100644 (file)
index 0000000..fed3696
--- /dev/null
@@ -0,0 +1,200 @@
+// 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/platform_file.h"
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+
+#if defined(OS_ANDROID)
+#include "base/os_compat_android.h"
+#endif
+
+namespace base {
+
+#if defined(OS_OPENBSD) || defined(OS_FREEBSD) || \
+    (defined(OS_MACOSX) && \
+     MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
+typedef struct stat stat_wrapper_t;
+static int CallFstat(int fd, stat_wrapper_t *sb) {
+  return fstat(fd, sb);
+}
+#else
+typedef struct stat64 stat_wrapper_t;
+static int CallFstat(int fd, stat_wrapper_t *sb) {
+  return fstat64(fd, sb);
+}
+#endif
+
+// TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
+PlatformFile CreatePlatformFile(const FilePath& name, int flags,
+                                bool* created, PlatformFileError* error_code) {
+  int open_flags = 0;
+  if (flags & PLATFORM_FILE_CREATE)
+    open_flags = O_CREAT | O_EXCL;
+
+  if (created)
+    *created = false;
+
+  if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
+    DCHECK(!open_flags);
+    open_flags = O_CREAT | O_TRUNC;
+  }
+
+  if (flags & PLATFORM_FILE_OPEN_TRUNCATED) {
+    DCHECK(!open_flags);
+    DCHECK(flags & PLATFORM_FILE_WRITE);
+    open_flags = O_TRUNC;
+  }
+
+  if (!open_flags && !(flags & PLATFORM_FILE_OPEN) &&
+      !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
+    NOTREACHED();
+    errno = EOPNOTSUPP;
+    if (error_code)
+      *error_code = PLATFORM_FILE_ERROR_FAILED;
+    return kInvalidPlatformFileValue;
+  }
+
+  if (flags & PLATFORM_FILE_WRITE && flags & PLATFORM_FILE_READ) {
+    open_flags |= O_RDWR;
+  } else if (flags & PLATFORM_FILE_WRITE) {
+    open_flags |= O_WRONLY;
+  } else if (!(flags & PLATFORM_FILE_READ) &&
+             !(flags & PLATFORM_FILE_WRITE_ATTRIBUTES) &&
+             !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
+    NOTREACHED();
+  }
+
+  COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
+
+  int descriptor =
+      HANDLE_EINTR(open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR));
+
+  if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
+    if (descriptor <= 0) {
+      open_flags |= O_CREAT;
+      if (flags & PLATFORM_FILE_EXCLUSIVE_READ ||
+          flags & PLATFORM_FILE_EXCLUSIVE_WRITE) {
+        open_flags |= O_EXCL;   // together with O_CREAT implies O_NOFOLLOW
+      }
+      descriptor = HANDLE_EINTR(
+          open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR));
+      if (created && descriptor > 0)
+        *created = true;
+    }
+  }
+
+  if (created && (descriptor > 0) &&
+      (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE)))
+    *created = true;
+
+  if ((descriptor > 0) && (flags & PLATFORM_FILE_DELETE_ON_CLOSE)) {
+    unlink(name.value().c_str());
+  }
+
+  if (error_code) {
+    if (descriptor >= 0)
+      *error_code = PLATFORM_FILE_OK;
+    else {
+      switch (errno) {
+        case EACCES:
+        case EISDIR:
+        case EROFS:
+        case EPERM:
+          *error_code = PLATFORM_FILE_ERROR_ACCESS_DENIED;
+          break;
+        case ETXTBSY:
+          *error_code = PLATFORM_FILE_ERROR_IN_USE;
+          break;
+        case EEXIST:
+          *error_code = PLATFORM_FILE_ERROR_EXISTS;
+          break;
+        case ENOENT:
+          *error_code = PLATFORM_FILE_ERROR_NOT_FOUND;
+          break;
+        case EMFILE:
+          *error_code = PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
+          break;
+        case ENOMEM:
+          *error_code = PLATFORM_FILE_ERROR_NO_MEMORY;
+          break;
+        case ENOSPC:
+          *error_code = PLATFORM_FILE_ERROR_NO_SPACE;
+          break;
+        case ENOTDIR:
+          *error_code = PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+          break;
+        default:
+          *error_code = PLATFORM_FILE_ERROR_FAILED;
+      }
+    }
+  }
+
+  return descriptor;
+}
+
+bool ClosePlatformFile(PlatformFile file) {
+  return !HANDLE_EINTR(close(file));
+}
+
+int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
+  if (file < 0)
+    return -1;
+
+  return HANDLE_EINTR(pread(file, data, size, offset));
+}
+
+int WritePlatformFile(PlatformFile file, int64 offset,
+                      const char* data, int size) {
+  if (file < 0)
+    return -1;
+
+  return HANDLE_EINTR(pwrite(file, data, size, offset));
+}
+
+bool TruncatePlatformFile(PlatformFile file, int64 length) {
+  return ((file >= 0) && !HANDLE_EINTR(ftruncate(file, length)));
+}
+
+bool FlushPlatformFile(PlatformFile file) {
+  return !HANDLE_EINTR(fsync(file));
+}
+
+bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
+                       const base::Time& last_modified_time) {
+  if (file < 0)
+    return false;
+
+  timeval times[2];
+  times[0] = last_access_time.ToTimeVal();
+  times[1] = last_modified_time.ToTimeVal();
+  return !futimes(file, times);
+}
+
+bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
+  if (!info)
+    return false;
+
+  stat_wrapper_t file_info;
+  if (CallFstat(file, &file_info))
+    return false;
+
+  info->is_directory = S_ISDIR(file_info.st_mode);
+  info->is_symbolic_link = S_ISLNK(file_info.st_mode);
+  info->size = file_info.st_size;
+  info->last_modified = base::Time::FromTimeT(file_info.st_mtime);
+  info->last_accessed = base::Time::FromTimeT(file_info.st_atime);
+  info->creation_time = base::Time::FromTimeT(file_info.st_ctime);
+  return true;
+}
+
+}  // namespace base
diff --git a/base/port.h b/base/port.h
new file mode 100644 (file)
index 0000000..2e66057
--- /dev/null
@@ -0,0 +1,55 @@
+// 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_PORT_H_
+#define BASE_PORT_H_
+#pragma once
+
+#include <stdarg.h>
+#include "build/build_config.h"
+
+#ifdef COMPILER_MSVC
+#define GG_LONGLONG(x) x##I64
+#define GG_ULONGLONG(x) x##UI64
+#else
+#define GG_LONGLONG(x) x##LL
+#define GG_ULONGLONG(x) x##ULL
+#endif
+
+// Per C99 7.8.14, define __STDC_CONSTANT_MACROS before including <stdint.h>
+// to get the INTn_C and UINTn_C macros for integer constants.  It's difficult
+// to guarantee any specific ordering of header includes, so it's difficult to
+// guarantee that the INTn_C macros can be defined by including <stdint.h> at
+// any specific point.  Provide GG_INTn_C macros instead.
+
+#define GG_INT8_C(x)    (x)
+#define GG_INT16_C(x)   (x)
+#define GG_INT32_C(x)   (x)
+#define GG_INT64_C(x)   GG_LONGLONG(x)
+
+#define GG_UINT8_C(x)   (x ## U)
+#define GG_UINT16_C(x)  (x ## U)
+#define GG_UINT32_C(x)  (x ## U)
+#define GG_UINT64_C(x)  GG_ULONGLONG(x)
+
+// It's possible for functions that use a va_list, such as StringPrintf, to
+// invalidate the data in it upon use.  The fix is to make a copy of the
+// structure before using it and use that copy instead.  va_copy is provided
+// for this purpose.  MSVC does not provide va_copy, so define an
+// implementation here.  It is not guaranteed that assignment is a copy, so the
+// StringUtil.VariableArgsFunc unit test tests this capability.
+#if defined(COMPILER_GCC)
+#define GG_VA_COPY(a, b) (va_copy(a, b))
+#elif defined(COMPILER_MSVC)
+#define GG_VA_COPY(a, b) (a = b)
+#endif
+
+// Define an OS-neutral wrapper for shared library entry points
+#if defined(OS_WIN)
+#define API_CALL __stdcall
+#else
+#define API_CALL
+#endif
+
+#endif  // BASE_PORT_H_
diff --git a/base/string16.cc b/base/string16.cc
new file mode 100644 (file)
index 0000000..6fc38ce
--- /dev/null
@@ -0,0 +1,80 @@
+// 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/string16.h"
+
+#if defined(WCHAR_T_IS_UTF16)
+
+#error This file should not be used on 2-byte wchar_t systems
+// If this winds up being needed on 2-byte wchar_t systems, either the
+// definitions below can be used, or the host system's wide character
+// functions like wmemcmp can be wrapped.
+
+#elif defined(WCHAR_T_IS_UTF32)
+
+#include <ostream>
+
+#include "base/utf_string_conversions.h"
+
+namespace base {
+
+int c16memcmp(const char16* s1, const char16* s2, size_t n) {
+  // We cannot call memcmp because that changes the semantics.
+  while (n-- > 0) {
+    if (*s1 != *s2) {
+      // We cannot use (*s1 - *s2) because char16 is unsigned.
+      return ((*s1 < *s2) ? -1 : 1);
+    }
+    ++s1;
+    ++s2;
+  }
+  return 0;
+}
+
+size_t c16len(const char16* s) {
+  const char16 *s_orig = s;
+  while (*s) {
+    ++s;
+  }
+  return s - s_orig;
+}
+
+const char16* c16memchr(const char16* s, char16 c, size_t n) {
+  while (n-- > 0) {
+    if (*s == c) {
+      return s;
+    }
+    ++s;
+  }
+  return 0;
+}
+
+char16* c16memmove(char16* s1, const char16* s2, size_t n) {
+  return reinterpret_cast<char16*>(memmove(s1, s2, n * sizeof(char16)));
+}
+
+char16* c16memcpy(char16* s1, const char16* s2, size_t n) {
+  return reinterpret_cast<char16*>(memcpy(s1, s2, n * sizeof(char16)));
+}
+
+char16* c16memset(char16* s, char16 c, size_t n) {
+  char16 *s_orig = s;
+  while (n-- > 0) {
+    *s = c;
+    ++s;
+  }
+  return s_orig;
+}
+
+}  // namespace base
+
+template class std::basic_string<char16, base::string16_char_traits>;
+
+namespace base {
+std::ostream& operator<<(std::ostream& out, const string16& str) {
+  return out << UTF16ToUTF8(str);
+}
+}
+
+#endif  // WCHAR_T_IS_UTF32
diff --git a/base/string16.h b/base/string16.h
new file mode 100644 (file)
index 0000000..4c7b21f
--- /dev/null
@@ -0,0 +1,178 @@
+// 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_STRING16_H_
+#define BASE_STRING16_H_
+#pragma once
+
+// WHAT:
+// A version of std::basic_string that provides 2-byte characters even when
+// wchar_t is not implemented as a 2-byte type. You can access this class as
+// string16. We also define char16, which string16 is based upon.
+//
+// WHY:
+// On Windows, wchar_t is 2 bytes, and it can conveniently handle UTF-16/UCS-2
+// data. Plenty of existing code operates on strings encoded as UTF-16.
+//
+// On many other platforms, sizeof(wchar_t) is 4 bytes by default. We can make
+// it 2 bytes by using the GCC flag -fshort-wchar. But then std::wstring fails
+// at run time, because it calls some functions (like wcslen) that come from
+// the system's native C library -- which was built with a 4-byte wchar_t!
+// It's wasteful to use 4-byte wchar_t strings to carry UTF-16 data, and it's
+// entirely improper on those systems where the encoding of wchar_t is defined
+// as UTF-32.
+//
+// Here, we define string16, which is similar to std::wstring but replaces all
+// libc functions with custom, 2-byte-char compatible routines. It is capable
+// of carrying UTF-16-encoded data.
+
+#include <stdio.h>
+#include <string>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+
+#if defined(WCHAR_T_IS_UTF16)
+
+typedef wchar_t char16;
+typedef std::wstring string16;
+
+#elif defined(WCHAR_T_IS_UTF32)
+
+typedef uint16 char16;
+
+namespace base {
+
+// char16 versions of the functions required by string16_char_traits; these
+// are based on the wide character functions of similar names ("w" or "wcs"
+// instead of "c16").
+BASE_EXPORT int c16memcmp(const char16* s1, const char16* s2, size_t n);
+BASE_EXPORT size_t c16len(const char16* s);
+BASE_EXPORT const char16* c16memchr(const char16* s, char16 c, size_t n);
+BASE_EXPORT char16* c16memmove(char16* s1, const char16* s2, size_t n);
+BASE_EXPORT char16* c16memcpy(char16* s1, const char16* s2, size_t n);
+BASE_EXPORT char16* c16memset(char16* s, char16 c, size_t n);
+
+struct string16_char_traits {
+  typedef char16 char_type;
+  typedef int int_type;
+
+  // int_type needs to be able to hold each possible value of char_type, and in
+  // addition, the distinct value of eof().
+  COMPILE_ASSERT(sizeof(int_type) > sizeof(char_type), unexpected_type_width);
+
+  typedef std::streamoff off_type;
+  typedef mbstate_t state_type;
+  typedef std::fpos<state_type> pos_type;
+
+  static void assign(char_type& c1, const char_type& c2) {
+    c1 = c2;
+  }
+
+  static bool eq(const char_type& c1, const char_type& c2) {
+    return c1 == c2;
+  }
+  static bool lt(const char_type& c1, const char_type& c2) {
+    return c1 < c2;
+  }
+
+  static int compare(const char_type* s1, const char_type* s2, size_t n) {
+    return c16memcmp(s1, s2, n);
+  }
+
+  static size_t length(const char_type* s) {
+    return c16len(s);
+  }
+
+  static const char_type* find(const char_type* s, size_t n,
+                               const char_type& a) {
+    return c16memchr(s, a, n);
+  }
+
+  static char_type* move(char_type* s1, const char_type* s2, int_type n) {
+    return c16memmove(s1, s2, n);
+  }
+
+  static char_type* copy(char_type* s1, const char_type* s2, size_t n) {
+    return c16memcpy(s1, s2, n);
+  }
+
+  static char_type* assign(char_type* s, size_t n, char_type a) {
+    return c16memset(s, a, n);
+  }
+
+  static int_type not_eof(const int_type& c) {
+    return eq_int_type(c, eof()) ? 0 : c;
+  }
+
+  static char_type to_char_type(const int_type& c) {
+    return char_type(c);
+  }
+
+  static int_type to_int_type(const char_type& c) {
+    return int_type(c);
+  }
+
+  static bool eq_int_type(const int_type& c1, const int_type& c2) {
+    return c1 == c2;
+  }
+
+  static int_type eof() {
+    return static_cast<int_type>(EOF);
+  }
+};
+
+}  // namespace base
+
+// The string class will be explicitly instantiated only once, in string16.cc.
+//
+// std::basic_string<> in GNU libstdc++ contains a static data member,
+// _S_empty_rep_storage, to represent empty strings.  When an operation such
+// as assignment or destruction is performed on a string, causing its existing
+// data member to be invalidated, it must not be freed if this static data
+// member is being used.  Otherwise, it counts as an attempt to free static
+// (and not allocated) data, which is a memory error.
+//
+// Generally, due to C++ template magic, _S_empty_rep_storage will be marked
+// as a coalesced symbol, meaning that the linker will combine multiple
+// instances into a single one when generating output.
+//
+// If a string class is used by multiple shared libraries, a problem occurs.
+// Each library will get its own copy of _S_empty_rep_storage.  When strings
+// are passed across a library boundary for alteration or destruction, memory
+// errors will result.  GNU libstdc++ contains a configuration option,
+// --enable-fully-dynamic-string (_GLIBCXX_FULLY_DYNAMIC_STRING), which
+// disables the static data member optimization, but it's a good optimization
+// and non-STL code is generally at the mercy of the system's STL
+// configuration.  Fully-dynamic strings are not the default for GNU libstdc++
+// libstdc++ itself or for the libstdc++ installations on the systems we care
+// about, such as Mac OS X and relevant flavors of Linux.
+//
+// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24196 .
+//
+// To avoid problems, string classes need to be explicitly instantiated only
+// once, in exactly one library.  All other string users see it via an "extern"
+// declaration.  This is precisely how GNU libstdc++ handles
+// std::basic_string<char> (string) and std::basic_string<wchar_t> (wstring).
+//
+// This also works around a Mac OS X linker bug in ld64-85.2.1 (Xcode 3.1.2),
+// in which the linker does not fully coalesce symbols when dead code
+// stripping is enabled.  This bug causes the memory errors described above
+// to occur even when a std::basic_string<> does not cross shared library
+// boundaries, such as in statically-linked executables.
+//
+// TODO(mark): File this bug with Apple and update this note with a bug number.
+
+extern template class std::basic_string<char16, base::string16_char_traits>;
+
+typedef std::basic_string<char16, base::string16_char_traits> string16;
+
+namespace base {
+BASE_EXPORT extern std::ostream& operator<<(std::ostream& out,
+                                            const string16& str);
+}
+
+#endif  // WCHAR_T_IS_UTF32
+
+#endif  // BASE_STRING16_H_
diff --git a/base/string_number_conversions.cc b/base/string_number_conversions.cc
new file mode 100644 (file)
index 0000000..54eca17
--- /dev/null
@@ -0,0 +1,545 @@
+// 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/string_number_conversions.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <wctype.h>
+
+#include <limits>
+
+#include "base/logging.h"
+#include "base/third_party/dmg_fp/dmg_fp.h"
+#include "base/utf_string_conversions.h"
+
+namespace base {
+
+namespace {
+
+template <typename STR, typename INT, typename UINT, bool NEG>
+struct IntToStringT {
+  // This is to avoid a compiler warning about unary minus on unsigned type.
+  // For example, say you had the following code:
+  //   template <typename INT>
+  //   INT abs(INT value) { return value < 0 ? -value : value; }
+  // Even though if INT is unsigned, it's impossible for value < 0, so the
+  // unary minus will never be taken, the compiler will still generate a
+  // warning.  We do a little specialization dance...
+  template <typename INT2, typename UINT2, bool NEG2>
+  struct ToUnsignedT {};
+
+  template <typename INT2, typename UINT2>
+  struct ToUnsignedT<INT2, UINT2, false> {
+    static UINT2 ToUnsigned(INT2 value) {
+      return static_cast<UINT2>(value);
+    }
+  };
+
+  template <typename INT2, typename UINT2>
+  struct ToUnsignedT<INT2, UINT2, true> {
+    static UINT2 ToUnsigned(INT2 value) {
+      return static_cast<UINT2>(value < 0 ? -value : value);
+    }
+  };
+
+  // This set of templates is very similar to the above templates, but
+  // for testing whether an integer is negative.
+  template <typename INT2, bool NEG2>
+  struct TestNegT {};
+  template <typename INT2>
+  struct TestNegT<INT2, false> {
+    static bool TestNeg(INT2 value) {
+      // value is unsigned, and can never be negative.
+      return false;
+    }
+  };
+  template <typename INT2>
+  struct TestNegT<INT2, true> {
+    static bool TestNeg(INT2 value) {
+      return value < 0;
+    }
+  };
+
+  static STR IntToString(INT value) {
+    // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4.
+    // So round up to allocate 3 output characters per byte, plus 1 for '-'.
+    const int kOutputBufSize = 3 * sizeof(INT) + 1;
+
+    // Allocate the whole string right away, we will right back to front, and
+    // then return the substr of what we ended up using.
+    STR outbuf(kOutputBufSize, 0);
+
+    bool is_neg = TestNegT<INT, NEG>::TestNeg(value);
+    // Even though is_neg will never be true when INT is parameterized as
+    // unsigned, even the presence of the unary operation causes a warning.
+    UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value);
+
+    for (typename STR::iterator it = outbuf.end();;) {
+      --it;
+      DCHECK(it != outbuf.begin());
+      *it = static_cast<typename STR::value_type>((res % 10) + '0');
+      res /= 10;
+
+      // We're done..
+      if (res == 0) {
+        if (is_neg) {
+          --it;
+          DCHECK(it != outbuf.begin());
+          *it = static_cast<typename STR::value_type>('-');
+        }
+        return STR(it, outbuf.end());
+      }
+    }
+    NOTREACHED();
+    return STR();
+  }
+};
+
+// Utility to convert a character to a digit in a given base
+template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit {
+};
+
+// Faster specialization for bases <= 10
+template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> {
+ public:
+  static bool Convert(CHAR c, uint8* digit) {
+    if (c >= '0' && c < '0' + BASE) {
+      *digit = c - '0';
+      return true;
+    }
+    return false;
+  }
+};
+
+// Specialization for bases where 10 < base <= 36
+template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
+ public:
+  static bool Convert(CHAR c, uint8* digit) {
+    if (c >= '0' && c <= '9') {
+      *digit = c - '0';
+    } else if (c >= 'a' && c < 'a' + BASE - 10) {
+      *digit = c - 'a' + 10;
+    } else if (c >= 'A' && c < 'A' + BASE - 10) {
+      *digit = c - 'A' + 10;
+    } else {
+      return false;
+    }
+    return true;
+  }
+};
+
+template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8* digit) {
+  return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit);
+}
+
+// There is an IsWhitespace for wchars defined in string_util.h, but it is
+// locale independent, whereas the functions we are replacing were
+// locale-dependent. TBD what is desired, but for the moment let's not introduce
+// a change in behaviour.
+template<typename CHAR> class WhitespaceHelper {
+};
+
+template<> class WhitespaceHelper<char> {
+ public:
+  static bool Invoke(char c) {
+    return 0 != isspace(static_cast<unsigned char>(c));
+  }
+};
+
+template<> class WhitespaceHelper<char16> {
+ public:
+  static bool Invoke(char16 c) {
+    return 0 != iswspace(c);
+  }
+};
+
+template<typename CHAR> bool LocalIsWhitespace(CHAR c) {
+  return WhitespaceHelper<CHAR>::Invoke(c);
+}
+
+// IteratorRangeToNumberTraits should provide:
+//  - a typedef for iterator_type, the iterator type used as input.
+//  - a typedef for value_type, the target numeric type.
+//  - static functions min, max (returning the minimum and maximum permitted
+//    values)
+//  - constant kBase, the base in which to interpret the input
+template<typename IteratorRangeToNumberTraits>
+class IteratorRangeToNumber {
+ public:
+  typedef IteratorRangeToNumberTraits traits;
+  typedef typename traits::iterator_type const_iterator;
+  typedef typename traits::value_type value_type;
+
+  // Generalized iterator-range-to-number conversion.
+  //
+  static bool Invoke(const_iterator begin,
+                     const_iterator end,
+                     value_type* output) {
+    bool valid = true;
+
+    while (begin != end && LocalIsWhitespace(*begin)) {
+      valid = false;
+      ++begin;
+    }
+
+    if (begin != end && *begin == '-') {
+      if (!Negative::Invoke(begin + 1, end, output)) {
+        valid = false;
+      }
+    } else {
+      if (begin != end && *begin == '+') {
+        ++begin;
+      }
+      if (!Positive::Invoke(begin, end, output)) {
+        valid = false;
+      }
+    }
+
+    return valid;
+  }
+
+ private:
+  // Sign provides:
+  //  - a static function, CheckBounds, that determines whether the next digit
+  //    causes an overflow/underflow
+  //  - a static function, Increment, that appends the next digit appropriately
+  //    according to the sign of the number being parsed.
+  template<typename Sign>
+  class Base {
+   public:
+    static bool Invoke(const_iterator begin, const_iterator end,
+                       typename traits::value_type* output) {
+      *output = 0;
+
+      if (begin == end) {
+        return false;
+      }
+
+      // Note: no performance difference was found when using template
+      // specialization to remove this check in bases other than 16
+      if (traits::kBase == 16 && end - begin > 2 && *begin == '0' &&
+          (*(begin + 1) == 'x' || *(begin + 1) == 'X')) {
+        begin += 2;
+      }
+
+      for (const_iterator current = begin; current != end; ++current) {
+        uint8 new_digit = 0;
+
+        if (!CharToDigit<traits::kBase>(*current, &new_digit)) {
+          return false;
+        }
+
+        if (current != begin) {
+          if (!Sign::CheckBounds(output, new_digit)) {
+            return false;
+          }
+          *output *= traits::kBase;
+        }
+
+        Sign::Increment(new_digit, output);
+      }
+      return true;
+    }
+  };
+
+  class Positive : public Base<Positive> {
+   public:
+    static bool CheckBounds(value_type* output, uint8 new_digit) {
+      if (*output > static_cast<value_type>(traits::max() / traits::kBase) ||
+          (*output == static_cast<value_type>(traits::max() / traits::kBase) &&
+           new_digit > traits::max() % traits::kBase)) {
+        *output = traits::max();
+        return false;
+      }
+      return true;
+    }
+    static void Increment(uint8 increment, value_type* output) {
+      *output += increment;
+    }
+  };
+
+  class Negative : public Base<Negative> {
+   public:
+    static bool CheckBounds(value_type* output, uint8 new_digit) {
+      if (*output < traits::min() / traits::kBase ||
+          (*output == traits::min() / traits::kBase &&
+           new_digit > 0 - traits::min() % traits::kBase)) {
+        *output = traits::min();
+        return false;
+      }
+      return true;
+    }
+    static void Increment(uint8 increment, value_type* output) {
+      *output -= increment;
+    }
+  };
+};
+
+template<typename ITERATOR, typename VALUE, int BASE>
+class BaseIteratorRangeToNumberTraits {
+ public:
+  typedef ITERATOR iterator_type;
+  typedef VALUE value_type;
+  static value_type min() {
+    return std::numeric_limits<value_type>::min();
+  }
+  static value_type max() {
+    return std::numeric_limits<value_type>::max();
+  }
+  static const int kBase = BASE;
+};
+
+typedef BaseIteratorRangeToNumberTraits<std::string::const_iterator, int, 10>
+    IteratorRangeToIntTraits;
+typedef BaseIteratorRangeToNumberTraits<string16::const_iterator, int, 10>
+    WideIteratorRangeToIntTraits;
+typedef BaseIteratorRangeToNumberTraits<std::string::const_iterator, int64, 10>
+    IteratorRangeToInt64Traits;
+typedef BaseIteratorRangeToNumberTraits<string16::const_iterator, int64, 10>
+    WideIteratorRangeToInt64Traits;
+
+typedef BaseIteratorRangeToNumberTraits<const char*, int, 10>
+    CharBufferToIntTraits;
+typedef BaseIteratorRangeToNumberTraits<const char16*, int, 10>
+    WideCharBufferToIntTraits;
+typedef BaseIteratorRangeToNumberTraits<const char*, int64, 10>
+    CharBufferToInt64Traits;
+typedef BaseIteratorRangeToNumberTraits<const char16*, int64, 10>
+    WideCharBufferToInt64Traits;
+
+template<typename ITERATOR>
+class BaseHexIteratorRangeToIntTraits
+    : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> {
+ public:
+  // Allow parsing of 0xFFFFFFFF, which is technically an overflow
+  static unsigned int max() {
+    return std::numeric_limits<unsigned int>::max();
+  }
+};
+
+typedef BaseHexIteratorRangeToIntTraits<std::string::const_iterator>
+    HexIteratorRangeToIntTraits;
+typedef BaseHexIteratorRangeToIntTraits<const char*>
+    HexCharBufferToIntTraits;
+
+template<typename STR>
+bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) {
+  DCHECK_EQ(output->size(), 0u);
+  size_t count = input.size();
+  if (count == 0 || (count % 2) != 0)
+    return false;
+  for (uintptr_t i = 0; i < count / 2; ++i) {
+    uint8 msb = 0;  // most significant 4 bits
+    uint8 lsb = 0;  // least significant 4 bits
+    if (!CharToDigit<16>(input[i * 2], &msb) ||
+        !CharToDigit<16>(input[i * 2 + 1], &lsb))
+      return false;
+    output->push_back((msb << 4) | lsb);
+  }
+  return true;
+}
+
+}  // namespace
+
+std::string IntToString(int value) {
+  return IntToStringT<std::string, int, unsigned int, true>::
+      IntToString(value);
+}
+
+string16 IntToString16(int value) {
+  return IntToStringT<string16, int, unsigned int, true>::
+      IntToString(value);
+}
+
+std::string UintToString(unsigned int value) {
+  return IntToStringT<std::string, unsigned int, unsigned int, false>::
+      IntToString(value);
+}
+
+string16 UintToString16(unsigned int value) {
+  return IntToStringT<string16, unsigned int, unsigned int, false>::
+      IntToString(value);
+}
+
+std::string Int64ToString(int64 value) {
+  return IntToStringT<std::string, int64, uint64, true>::
+      IntToString(value);
+}
+
+string16 Int64ToString16(int64 value) {
+  return IntToStringT<string16, int64, uint64, true>::IntToString(value);
+}
+
+std::string Uint64ToString(uint64 value) {
+  return IntToStringT<std::string, uint64, uint64, false>::
+      IntToString(value);
+}
+
+string16 Uint64ToString16(uint64 value) {
+  return IntToStringT<string16, uint64, uint64, false>::
+      IntToString(value);
+}
+
+std::string DoubleToString(double value) {
+  // According to g_fmt.cc, it is sufficient to declare a buffer of size 32.
+  char buffer[32];
+  dmg_fp::g_fmt(buffer, value);
+  return std::string(buffer);
+}
+
+bool StringToInt(const std::string& input, int* output) {
+  return IteratorRangeToNumber<IteratorRangeToIntTraits>::Invoke(input.begin(),
+                                                                 input.end(),
+                                                                 output);
+}
+
+bool StringToInt(std::string::const_iterator begin,
+                 std::string::const_iterator end,
+                 int* output) {
+  return IteratorRangeToNumber<IteratorRangeToIntTraits>::Invoke(begin,
+                                                                 end,
+                                                                 output);
+}
+
+#if !defined(STD_STRING_ITERATOR_IS_CHAR_POINTER)
+bool StringToInt(const char* begin, const char* end, int* output) {
+  return IteratorRangeToNumber<CharBufferToIntTraits>::Invoke(begin,
+                                                              end,
+                                                              output);
+}
+#endif
+
+bool StringToInt(const string16& input, int* output) {
+  return IteratorRangeToNumber<WideIteratorRangeToIntTraits>::Invoke(
+    input.begin(), input.end(), output);
+}
+
+bool StringToInt(string16::const_iterator begin,
+                 string16::const_iterator end,
+                 int* output) {
+  return IteratorRangeToNumber<WideIteratorRangeToIntTraits>::Invoke(begin,
+                                                                     end,
+                                                                     output);
+}
+
+#if !defined(BASE_STRING16_ITERATOR_IS_CHAR16_POINTER)
+bool StringToInt(const char16* begin, const char16* end, int* output) {
+  return IteratorRangeToNumber<WideCharBufferToIntTraits>::Invoke(begin,
+                                                                  end,
+                                                                  output);
+}
+#endif
+
+bool StringToInt64(const std::string& input, int64* output) {
+  return IteratorRangeToNumber<IteratorRangeToInt64Traits>::Invoke(
+    input.begin(), input.end(), output);
+}
+
+bool StringToInt64(std::string::const_iterator begin,
+                 std::string::const_iterator end,
+                 int64* output) {
+  return IteratorRangeToNumber<IteratorRangeToInt64Traits>::Invoke(begin,
+                                                                 end,
+                                                                 output);
+}
+
+#if !defined(STD_STRING_ITERATOR_IS_CHAR_POINTER)
+bool StringToInt64(const char* begin, const char* end, int64* output) {
+  return IteratorRangeToNumber<CharBufferToInt64Traits>::Invoke(begin,
+                                                              end,
+                                                              output);
+}
+#endif
+
+bool StringToInt64(const string16& input, int64* output) {
+  return IteratorRangeToNumber<WideIteratorRangeToInt64Traits>::Invoke(
+    input.begin(), input.end(), output);
+}
+
+bool StringToInt64(string16::const_iterator begin,
+                 string16::const_iterator end,
+                 int64* output) {
+  return IteratorRangeToNumber<WideIteratorRangeToInt64Traits>::Invoke(begin,
+                                                                     end,
+                                                                     output);
+}
+
+#if !defined(BASE_STRING16_ITERATOR_IS_CHAR16_POINTER)
+bool StringToInt64(const char16* begin, const char16* end, int64* output) {
+  return IteratorRangeToNumber<WideCharBufferToInt64Traits>::Invoke(begin,
+                                                                  end,
+                                                                  output);
+}
+#endif
+
+bool StringToDouble(const std::string& input, double* output) {
+  errno = 0;  // Thread-safe?  It is on at least Mac, Linux, and Windows.
+  char* endptr = NULL;
+  *output = dmg_fp::strtod(input.c_str(), &endptr);
+
+  // Cases to return false:
+  //  - If errno is ERANGE, there was an overflow or underflow.
+  //  - If the input string is empty, there was nothing to parse.
+  //  - If endptr does not point to the end of the string, there are either
+  //    characters remaining in the string after a parsed number, or the string
+  //    does not begin with a parseable number.  endptr is compared to the
+  //    expected end given the string's stated length to correctly catch cases
+  //    where the string contains embedded NUL characters.
+  //  - If the first character is a space, there was leading whitespace
+  return errno == 0 &&
+         !input.empty() &&
+         input.c_str() + input.length() == endptr &&
+         !isspace(input[0]);
+}
+
+// Note: if you need to add String16ToDouble, first ask yourself if it's
+// really necessary. If it is, probably the best implementation here is to
+// convert to 8-bit and then use the 8-bit version.
+
+// Note: if you need to add an iterator range version of StringToDouble, first
+// ask yourself if it's really necessary. If it is, probably the best
+// implementation here is to instantiate a string and use the string version.
+
+std::string HexEncode(const void* bytes, size_t size) {
+  static const char kHexChars[] = "0123456789ABCDEF";
+
+  // Each input byte creates two output hex characters.
+  std::string ret(size * 2, '\0');
+
+  for (size_t i = 0; i < size; ++i) {
+    char b = reinterpret_cast<const char*>(bytes)[i];
+    ret[(i * 2)] = kHexChars[(b >> 4) & 0xf];
+    ret[(i * 2) + 1] = kHexChars[b & 0xf];
+  }
+  return ret;
+}
+
+bool HexStringToInt(const std::string& input, int* output) {
+  return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke(
+    input.begin(), input.end(), output);
+}
+
+bool HexStringToInt(std::string::const_iterator begin,
+                    std::string::const_iterator end,
+                    int* output) {
+  return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke(begin,
+                                                                    end,
+                                                                    output);
+}
+
+#if !defined(STD_STRING_ITERATOR_IS_CHAR_POINTER)
+bool HexStringToInt(const char* begin, const char* end, int* output) {
+  return IteratorRangeToNumber<HexCharBufferToIntTraits>::Invoke(begin,
+                                                                    end,
+                                                                    output);
+}
+#endif
+
+bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) {
+  return HexStringToBytesT(input, output);
+}
+
+}  // namespace base
diff --git a/base/string_number_conversions.h b/base/string_number_conversions.h
new file mode 100644 (file)
index 0000000..6cf6a76
--- /dev/null
@@ -0,0 +1,124 @@
+// 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_STRING_NUMBER_CONVERSIONS_H_
+#define BASE_STRING_NUMBER_CONVERSIONS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/string16.h"
+
+// ----------------------------------------------------------------------------
+// IMPORTANT MESSAGE FROM YOUR SPONSOR
+//
+// This file contains no "wstring" variants. New code should use string16. If
+// you need to make old code work, use the UTF8 version and convert. Please do
+// not add wstring variants.
+//
+// Please do not add "convenience" functions for converting strings to integers
+// that return the value and ignore success/failure. That encourages people to
+// write code that doesn't properly handle the error conditions.
+// ----------------------------------------------------------------------------
+
+namespace base {
+
+// Number -> string conversions ------------------------------------------------
+
+BASE_EXPORT std::string IntToString(int value);
+BASE_EXPORT string16 IntToString16(int value);
+
+BASE_EXPORT std::string UintToString(unsigned value);
+BASE_EXPORT string16 UintToString16(unsigned value);
+
+BASE_EXPORT std::string Int64ToString(int64 value);
+BASE_EXPORT string16 Int64ToString16(int64 value);
+
+BASE_EXPORT std::string Uint64ToString(uint64 value);
+BASE_EXPORT 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.
+BASE_EXPORT std::string DoubleToString(double value);
+
+// String -> number conversions ------------------------------------------------
+
+// Perform a best-effort conversion of the input string to a numeric type,
+// setting |*output| to the result of the conversion.  Returns true for
+// "perfect" conversions; returns false in the following cases:
+//  - Overflow/underflow.  |*output| will be set to the maximum value supported
+//    by the data type.
+//  - Trailing characters in the string after parsing the number.  |*output|
+//    will be set to the value of the number that was parsed.
+//  - Leading whitespace in the string before parsing the number. |*output| will
+//    be set to the value of the number that was parsed.
+//  - 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.
+BASE_EXPORT bool StringToInt(const std::string& input, int* output);
+BASE_EXPORT bool StringToInt(std::string::const_iterator begin,
+                             std::string::const_iterator end,
+                             int* output);
+BASE_EXPORT bool StringToInt(const char* begin, const char* end, int* output);
+
+BASE_EXPORT bool StringToInt(const string16& input, int* output);
+BASE_EXPORT bool StringToInt(string16::const_iterator begin,
+                             string16::const_iterator end,
+                             int* output);
+BASE_EXPORT bool StringToInt(const char16* begin, const char16* end,
+                             int* output);
+
+BASE_EXPORT bool StringToInt64(const std::string& input, int64* output);
+BASE_EXPORT bool StringToInt64(std::string::const_iterator begin,
+                               std::string::const_iterator end,
+                               int64* output);
+BASE_EXPORT bool StringToInt64(const char* begin, const char* end,
+                               int64* output);
+
+BASE_EXPORT bool StringToInt64(const string16& input, int64* output);
+BASE_EXPORT bool StringToInt64(string16::const_iterator begin,
+                               string16::const_iterator end,
+                               int64* output);
+BASE_EXPORT 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
+// numbers in hexadecimal, and strings representing non-fininte values (such as
+// 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.
+BASE_EXPORT bool StringToDouble(const std::string& input, double* output);
+
+// Hex encoding ----------------------------------------------------------------
+
+// Returns a hex string representation of a binary buffer. The returned hex
+// string will be in upper case. This function does not check if |size| is
+// within reasonable limits since it's written with trusted data in mind.  If
+// 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
+BASE_EXPORT std::string HexEncode(const void* bytes, size_t size);
+
+// Best effort conversion, see StringToInt above for restrictions.
+BASE_EXPORT bool HexStringToInt(const std::string& input, int* output);
+BASE_EXPORT bool HexStringToInt(std::string::const_iterator begin,
+                                std::string::const_iterator end,
+                                int* output);
+BASE_EXPORT 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.
+BASE_EXPORT bool HexStringToBytes(const std::string& input,
+                                  std::vector<uint8>* output);
+
+}  // namespace base
+
+#endif  // BASE_STRING_NUMBER_CONVERSIONS_H_
+
diff --git a/base/string_piece.cc b/base/string_piece.cc
new file mode 100644 (file)
index 0000000..bf6291c
--- /dev/null
@@ -0,0 +1,214 @@
+// 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
+
+#include <algorithm>
+#include <ostream>
+
+#include "base/string_piece.h"
+
+namespace base {
+
+typedef StringPiece::size_type size_type;
+
+bool operator==(const StringPiece& x, const StringPiece& y) {
+  if (x.size() != y.size())
+    return false;
+
+  return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0;
+}
+
+void StringPiece::CopyToString(std::string* target) const {
+  target->assign(!empty() ? data() : "", size());
+}
+
+void StringPiece::AppendToString(std::string* target) const {
+  if (!empty())
+    target->append(data(), size());
+}
+
+size_type StringPiece::copy(char* buf, size_type n, size_type pos) const {
+  size_type ret = std::min(length_ - pos, n);
+  memcpy(buf, ptr_ + pos, ret);
+  return ret;
+}
+
+size_type StringPiece::find(const StringPiece& s, size_type pos) const {
+  if (pos > length_)
+    return npos;
+
+  const char* result = std::search(ptr_ + pos, ptr_ + length_,
+                                   s.ptr_, s.ptr_ + s.length_);
+  const size_type xpos = result - ptr_;
+  return xpos + s.length_ <= length_ ? xpos : npos;
+}
+
+size_type StringPiece::find(char c, size_type pos) const {
+  if (pos >= length_)
+    return npos;
+
+  const char* result = std::find(ptr_ + pos, ptr_ + length_, c);
+  return result != ptr_ + length_ ? static_cast<size_t>(result - ptr_) : npos;
+}
+
+size_type StringPiece::rfind(const StringPiece& s, size_type pos) const {
+  if (length_ < s.length_)
+    return npos;
+
+  if (s.empty())
+    return std::min(length_, pos);
+
+  const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
+  const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
+  return result != last ? static_cast<size_t>(result - ptr_) : npos;
+}
+
+size_type StringPiece::rfind(char c, size_type pos) const {
+  if (length_ == 0)
+    return npos;
+
+  for (size_type i = std::min(pos, length_ - 1); ; --i) {
+    if (ptr_[i] == c)
+      return i;
+    if (i == 0)
+      break;
+  }
+  return npos;
+}
+
+// For each character in characters_wanted, sets the index corresponding
+// to the ASCII code of that character to 1 in table.  This is used by
+// the find_.*_of methods below to tell whether or not a character is in
+// the lookup table in constant time.
+// The argument `table' must be an array that is large enough to hold all
+// the possible values of an unsigned char.  Thus it should be be declared
+// as follows:
+//   bool table[UCHAR_MAX + 1]
+static inline void BuildLookupTable(const StringPiece& characters_wanted,
+                                    bool* table) {
+  const size_type length = characters_wanted.length();
+  const char* const data = characters_wanted.data();
+  for (size_type i = 0; i < length; ++i) {
+    table[static_cast<unsigned char>(data[i])] = true;
+  }
+}
+
+size_type StringPiece::find_first_of(const StringPiece& s,
+                                     size_type pos) const {
+  if (length_ == 0 || s.length_ == 0)
+    return npos;
+
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1)
+    return find_first_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (size_type i = pos; i < length_; ++i) {
+    if (lookup[static_cast<unsigned char>(ptr_[i])]) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+size_type StringPiece::find_first_not_of(const StringPiece& s,
+                                         size_type pos) const {
+  if (length_ == 0)
+    return npos;
+
+  if (s.length_ == 0)
+    return 0;
+
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1)
+    return find_first_not_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (size_type i = pos; i < length_; ++i) {
+    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+size_type StringPiece::find_first_not_of(char c, size_type pos) const {
+  if (length_ == 0)
+    return npos;
+
+  for (; pos < length_; ++pos) {
+    if (ptr_[pos] != c) {
+      return pos;
+    }
+  }
+  return npos;
+}
+
+size_type StringPiece::find_last_of(const StringPiece& s, size_type pos) const {
+  if (length_ == 0 || s.length_ == 0)
+    return npos;
+
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1)
+    return find_last_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (size_type i = std::min(pos, length_ - 1); ; --i) {
+    if (lookup[static_cast<unsigned char>(ptr_[i])])
+      return i;
+    if (i == 0)
+      break;
+  }
+  return npos;
+}
+
+size_type StringPiece::find_last_not_of(const StringPiece& s,
+                                        size_type pos) const {
+  if (length_ == 0)
+    return npos;
+
+  size_type i = std::min(pos, length_ - 1);
+  if (s.length_ == 0)
+    return i;
+
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1)
+    return find_last_not_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (; ; --i) {
+    if (!lookup[static_cast<unsigned char>(ptr_[i])])
+      return i;
+    if (i == 0)
+      break;
+  }
+  return npos;
+}
+
+size_type StringPiece::find_last_not_of(char c, size_type pos) const {
+  if (length_ == 0)
+    return npos;
+
+  for (size_type i = std::min(pos, length_ - 1); ; --i) {
+    if (ptr_[i] != c)
+      return i;
+    if (i == 0)
+      break;
+  }
+  return npos;
+}
+
+StringPiece StringPiece::substr(size_type pos, size_type n) const {
+  if (pos > length_) pos = length_;
+  if (n > length_ - pos) n = length_ - pos;
+  return StringPiece(ptr_ + pos, n);
+}
+
+const StringPiece::size_type StringPiece::npos = size_type(-1);
+
+}  // namespace base
diff --git a/base/string_piece.h b/base/string_piece.h
new file mode 100644 (file)
index 0000000..278c7b6
--- /dev/null
@@ -0,0 +1,349 @@
+// 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.h with modifications
+//
+// A string-like object that points to a sized piece of memory.
+//
+// Functions or methods may use const StringPiece& parameters to accept either
+// a "const char*" or a "string" value that will be implicitly converted to
+// a StringPiece.  The implicit conversion means that it is often appropriate
+// to include this .h file in other files rather than forward-declaring
+// StringPiece as would be appropriate for most other Google classes.
+//
+// Systematic usage of StringPiece is encouraged as it will reduce unnecessary
+// conversions from "const char*" to "string" and back again.
+//
+// StringPiece16 is similar to StringPiece but for base::string16 instead of
+// std::string. We do not define as large of a subset of the STL functions
+// from basic_string as in StringPiece, but this can be changed if these
+// functions (find, find_first_of, etc.) are found to be useful in this context.
+//
+
+#ifndef BASE_STRING_PIECE_H_
+#define BASE_STRING_PIECE_H_
+#pragma once
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "base/string16.h"
+
+namespace base {
+
+class BASE_EXPORT StringPiece {
+ public:
+  // standard STL container boilerplate
+  typedef size_t size_type;
+  typedef char value_type;
+  typedef const char* pointer;
+  typedef const char& reference;
+  typedef const char& const_reference;
+  typedef ptrdiff_t difference_type;
+  typedef const char* const_iterator;
+  typedef const char* iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+
+  static const size_type npos;
+
+ public:
+  // We provide non-explicit singleton constructors so users can pass
+  // in a "const char*" or a "string" wherever a "StringPiece" is
+  // expected.
+  StringPiece() : ptr_(NULL), length_(0) { }
+  StringPiece(const char* str)
+    : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { }
+  StringPiece(const std::string& str)
+    : ptr_(str.data()), length_(str.size()) { }
+  StringPiece(const char* offset, size_type len)
+    : ptr_(offset), length_(len) { }
+
+  // data() may return a pointer to a buffer with embedded NULs, and the
+  // returned buffer may or may not be null terminated.  Therefore it is
+  // typically a mistake to pass data() to a routine that expects a NUL
+  // terminated string.
+  const char* data() const { return ptr_; }
+  size_type size() const { return length_; }
+  size_type length() const { return length_; }
+  bool empty() const { return length_ == 0; }
+
+  void clear() {
+    ptr_ = NULL;
+    length_ = 0;
+  }
+  void set(const char* data, size_type len) {
+    ptr_ = data;
+    length_ = len;
+  }
+  void set(const char* str) {
+    ptr_ = str;
+    length_ = str ? strlen(str) : 0;
+  }
+  void set(const void* data, size_type len) {
+    ptr_ = reinterpret_cast<const char*>(data);
+    length_ = len;
+  }
+
+  char operator[](size_type i) const { return ptr_[i]; }
+
+  void remove_prefix(size_type n) {
+    ptr_ += n;
+    length_ -= n;
+  }
+
+  void remove_suffix(size_type n) {
+    length_ -= n;
+  }
+
+  int compare(const StringPiece& x) const {
+    int r = wordmemcmp(
+        ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
+    if (r == 0) {
+      if (length_ < x.length_) r = -1;
+      else if (length_ > x.length_) r = +1;
+    }
+    return r;
+  }
+
+  std::string as_string() const {
+    // std::string doesn't like to take a NULL pointer even with a 0 size.
+    return std::string(!empty() ? data() : "", size());
+  }
+
+  void CopyToString(std::string* target) const;
+  void AppendToString(std::string* target) const;
+
+  // Does "this" start with "x"
+  bool starts_with(const StringPiece& x) const {
+    return ((length_ >= x.length_) &&
+            (wordmemcmp(ptr_, x.ptr_, x.length_) == 0));
+  }
+
+  // Does "this" end with "x"
+  bool ends_with(const StringPiece& x) const {
+    return ((length_ >= x.length_) &&
+            (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
+  }
+
+  iterator begin() const { return ptr_; }
+  iterator end() const { return ptr_ + length_; }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(ptr_ + length_);
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(ptr_);
+  }
+
+  size_type max_size() const { return length_; }
+  size_type capacity() const { return length_; }
+
+  size_type copy(char* buf, size_type n, size_type pos = 0) const;
+
+  size_type find(const StringPiece& s, size_type pos = 0) const;
+  size_type find(char c, size_type pos = 0) const;
+  size_type rfind(const StringPiece& s, size_type pos = npos) const;
+  size_type rfind(char c, size_type pos = npos) const;
+
+  size_type find_first_of(const StringPiece& s, size_type pos = 0) const;
+  size_type find_first_of(char c, size_type pos = 0) const {
+    return find(c, pos);
+  }
+  size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const;
+  size_type find_first_not_of(char c, size_type pos = 0) const;
+  size_type find_last_of(const StringPiece& s, size_type pos = npos) const;
+  size_type find_last_of(char c, size_type pos = npos) const {
+    return rfind(c, pos);
+  }
+  size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const;
+  size_type find_last_not_of(char c, size_type pos = npos) const;
+
+  StringPiece substr(size_type pos, size_type n = npos) const;
+
+  static int wordmemcmp(const char* p, const char* p2, size_type N) {
+    return memcmp(p, p2, N);
+  }
+
+ private:
+  const char*   ptr_;
+  size_type     length_;
+};
+
+class BASE_EXPORT StringPiece16 {
+ public:
+  // standard STL container boilerplate
+  typedef size_t size_type;
+  typedef char16 value_type;
+  typedef const char16* pointer;
+  typedef const char16& reference;
+  typedef const char16& const_reference;
+  typedef ptrdiff_t difference_type;
+  typedef const char16* const_iterator;
+  typedef const char16* iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ public:
+  // We provide non-explicit singleton constructors so users can pass
+  // in a "const char16*" or a "string16" wherever a "StringPiece16" is
+  // expected.
+  StringPiece16() : ptr_(NULL), length_(0) { }
+  StringPiece16(const char16* str)
+      : ptr_(str),
+        length_((str == NULL) ? 0 : string16::traits_type::length(str)) { }
+  StringPiece16(const string16& str)
+      : ptr_(str.data()), length_(str.size()) { }
+  StringPiece16(const char16* offset, size_type len)
+      : ptr_(offset), length_(len) { }
+
+  // data() may return a pointer to a buffer with embedded NULs, and the
+  // returned buffer may or may not be null terminated.  Therefore it is
+  // typically a mistake to pass data() to a routine that expects a NUL
+  // terminated string.
+  const char16* data() const { return ptr_; }
+  size_type size() const { return length_; }
+  size_type length() const { return length_; }
+  bool empty() const { return length_ == 0; }
+
+  void clear() {
+    ptr_ = NULL;
+    length_ = 0;
+  }
+  void set(const char16* data, size_type len) {
+    ptr_ = data;
+    length_ = len;
+  }
+  void set(const char16* str) {
+    ptr_ = str;
+    length_ = str ? string16::traits_type::length(str) : 0;
+  }
+
+  char16 operator[](size_type i) const { return ptr_[i]; }
+
+  string16 as_string16() const {
+    // StringPiece claims that this is bad when data() is NULL, but unittesting
+    // seems to say otherwise.
+    return string16(data(), size());
+  }
+
+  iterator begin() const { return ptr_; }
+  iterator end() const { return ptr_ + length_; }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(ptr_ + length_);
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(ptr_);
+  }
+
+  size_type max_size() const { return length_; }
+  size_type capacity() const { return length_; }
+
+  static int wordmemcmp(const char16* p, const char16* p2, size_type N) {
+    return string16::traits_type::compare(p, p2, N);
+  }
+
+ private:
+  const char16*   ptr_;
+  size_type       length_;
+};
+
+BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y);
+
+inline bool operator!=(const StringPiece& x, const StringPiece& y) {
+  return !(x == y);
+}
+
+inline bool operator<(const StringPiece& x, const StringPiece& y) {
+  const int r = StringPiece::wordmemcmp(
+      x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
+  return ((r < 0) || ((r == 0) && (x.size() < y.size())));
+}
+
+inline bool operator>(const StringPiece& x, const StringPiece& y) {
+  return y < x;
+}
+
+inline bool operator<=(const StringPiece& x, const StringPiece& y) {
+  return !(x > y);
+}
+
+inline bool operator>=(const StringPiece& x, const StringPiece& y) {
+  return !(x < y);
+}
+
+inline bool operator==(const StringPiece16& x, const StringPiece16& y) {
+  if (x.size() != y.size())
+    return false;
+
+  return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0;
+}
+
+inline bool operator!=(const StringPiece16& x, const StringPiece16& y) {
+  return !(x == y);
+}
+
+inline bool operator<(const StringPiece16& x, const StringPiece16& y) {
+  const int r = StringPiece16::wordmemcmp(
+      x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
+  return ((r < 0) || ((r == 0) && (x.size() < y.size())));
+}
+
+inline bool operator>(const StringPiece16& x, const StringPiece16& y) {
+  return y < x;
+}
+
+inline bool operator<=(const StringPiece16& x, const StringPiece16& y) {
+  return !(x > y);
+}
+
+inline bool operator>=(const StringPiece16& x, const StringPiece16& y) {
+  return !(x < y);
+}
+
+}  // namespace base
+
+// We provide appropriate hash functions so StringPiece and StringPiece16 can
+// be used as keys in hash sets and maps.
+
+// This hash function is copied from base/hash_tables.h. We don't use the
+// ones already defined for string and string16 directly because it would
+// require the string constructors to be called, which we don't want.
+#define HASH_STRING_PIECE(StringPieceType, string_piece)                \
+  std::size_t result = 0;                                               \
+  for (StringPieceType::const_iterator i = string_piece.begin();        \
+       i != string_piece.end(); ++i)                                    \
+    result = (result * 131) + *i;                                       \
+  return result;                                                        \
+
+namespace BASE_HASH_NAMESPACE {
+#if defined(COMPILER_GCC)
+
+template<>
+struct hash<base::StringPiece> {
+  std::size_t operator()(const base::StringPiece& sp) const {
+    HASH_STRING_PIECE(base::StringPiece, sp);
+  }
+};
+template<>
+struct hash<base::StringPiece16> {
+  std::size_t operator()(const base::StringPiece16& sp16) const {
+    HASH_STRING_PIECE(base::StringPiece16, sp16);
+  }
+};
+
+#elif defined(COMPILER_MSVC)
+
+inline size_t hash_value(const base::StringPiece& sp) {
+  HASH_STRING_PIECE(base::StringPiece, sp);
+}
+inline size_t hash_value(const base::StringPiece16& sp16) {
+  HASH_STRING_PIECE(base::StringPiece16, sp16);
+}
+
+#endif  // COMPILER
+
+}  // namespace BASE_HASH_NAMESPACE
+
+#endif  // BASE_STRING_PIECE_H_
diff --git a/base/synchronization/lock.h b/base/synchronization/lock.h
new file mode 100644 (file)
index 0000000..f3a685e
--- /dev/null
@@ -0,0 +1,132 @@
+// 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_SYNCHRONIZATION_LOCK_H_
+#define BASE_SYNCHRONIZATION_LOCK_H_
+#pragma once
+
+#include "base/base_export.h"
+#include "base/synchronization/lock_impl.h"
+#include "base/threading/platform_thread.h"
+
+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 BASE_EXPORT Lock {
+ public:
+#if defined(NDEBUG)             // Optimized wrapper implementation
+  Lock() : lock_() {}
+  ~Lock() {}
+  void Acquire() { lock_.Lock(); }
+  void Release() { lock_.Unlock(); }
+
+  // If the lock is not held, take it and return true. If the lock is already
+  // held by another thread, immediately return false. This must not be called
+  // by a thread already holding the lock (what happens is undefined and an
+  // assertion may fail).
+  bool Try() { return lock_.Try(); }
+
+  // Null implementation if not debug.
+  void AssertAcquired() const {}
+#else
+  Lock();
+  ~Lock() {}
+
+  // NOTE: Although windows critical sections support recursive locks, we do not
+  // allow this, and we will commonly fire a DCHECK() if a thread attempts to
+  // acquire the lock a second time (while already holding it).
+  void Acquire() {
+    lock_.Lock();
+    CheckUnheldAndMark();
+  }
+  void Release() {
+    CheckHeldAndUnmark();
+    lock_.Unlock();
+  }
+
+  bool Try() {
+    bool rv = lock_.Try();
+    if (rv) {
+      CheckUnheldAndMark();
+    }
+    return rv;
+  }
+
+  void AssertAcquired() const;
+#endif                          // NDEBUG
+
+#if defined(OS_POSIX)
+  // The posix implementation of ConditionVariable needs to be able
+  // to see our lock and tweak our debugging counters, as it releases
+  // and acquires locks inside of pthread_cond_{timed,}wait.
+  // Windows doesn't need to do this as it calls the Lock::* methods.
+  friend class ConditionVariable;
+#endif
+
+ private:
+#if !defined(NDEBUG)
+  // Members and routines taking care of locks assertions.
+  // Note that this checks for recursive locks and allows them
+  // if the variable is set.  This is allowed by the underlying implementation
+  // on windows but not on Posix, so we're doing unneeded checks on Posix.
+  // It's worth it to share the code.
+  void CheckHeldAndUnmark();
+  void CheckUnheldAndMark();
+
+  // All private data is implicitly protected by lock_.
+  // Be VERY careful to only access members under that lock.
+
+  // Determines validity of owning_thread_id_.  Needed as we don't have
+  // a null owning_thread_id_ value.
+  bool owned_by_thread_;
+  base::PlatformThreadId owning_thread_id_;
+#endif  // NDEBUG
+
+  // Platform specific underlying lock implementation.
+  internal::LockImpl lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(Lock);
+};
+
+// A helper class that acquires the given Lock while the AutoLock is in scope.
+class AutoLock {
+ public:
+  explicit AutoLock(Lock& lock) : lock_(lock) {
+    lock_.Acquire();
+  }
+
+  ~AutoLock() {
+    lock_.AssertAcquired();
+    lock_.Release();
+  }
+
+ private:
+  Lock& lock_;
+  DISALLOW_COPY_AND_ASSIGN(AutoLock);
+};
+
+// AutoUnlock is a helper that will Release() the |lock| argument in the
+// constructor, and re-Acquire() it in the destructor.
+class AutoUnlock {
+ public:
+  explicit AutoUnlock(Lock& lock) : lock_(lock) {
+    // We require our caller to have the lock.
+    lock_.AssertAcquired();
+    lock_.Release();
+  }
+
+  ~AutoUnlock() {
+    lock_.Acquire();
+  }
+
+ private:
+  Lock& lock_;
+  DISALLOW_COPY_AND_ASSIGN(AutoUnlock);
+};
+
+}  // namespace base
+
+#endif  // BASE_SYNCHRONIZATION_LOCK_H_
diff --git a/base/synchronization/lock_impl.h b/base/synchronization/lock_impl.h
new file mode 100644 (file)
index 0000000..63efc5f
--- /dev/null
@@ -0,0 +1,64 @@
+// 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_SYNCHRONIZATION_LOCK_IMPL_H_
+#define BASE_SYNCHRONIZATION_LOCK_IMPL_H_
+#pragma once
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_POSIX)
+#include <pthread.h>
+#endif
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+
+namespace base {
+namespace internal {
+
+// This class implements the underlying platform-specific spin-lock mechanism
+// used for the Lock class.  Most users should not use LockImpl directly, but
+// should instead use Lock.
+class BASE_EXPORT LockImpl {
+ public:
+#if defined(OS_WIN)
+  typedef CRITICAL_SECTION OSLockType;
+#elif defined(OS_POSIX)
+  typedef pthread_mutex_t OSLockType;
+#endif
+
+  LockImpl();
+  ~LockImpl();
+
+  // If the lock is not held, take it and return true.  If the lock is already
+  // held by something else, immediately return false.
+  bool Try();
+
+  // Take the lock, blocking until it is available if necessary.
+  void Lock();
+
+  // Release the lock.  This must only be called by the lock's holder: after
+  // a successful call to Try, or a call to Lock.
+  void Unlock();
+
+  // Return the native underlying lock.  Not supported for Windows builds.
+  // TODO(awalker): refactor lock and condition variables so that this is
+  // unnecessary.
+#if !defined(OS_WIN)
+  OSLockType* os_lock() { return &os_lock_; }
+#endif
+
+ private:
+  OSLockType os_lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(LockImpl);
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_SYNCHRONIZATION_LOCK_IMPL_H_
diff --git a/base/synchronization/waitable_event.h b/base/synchronization/waitable_event.h
new file mode 100644 (file)
index 0000000..62712ed
--- /dev/null
@@ -0,0 +1,181 @@
+// 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_SYNCHRONIZATION_WAITABLE_EVENT_H_
+#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
+#pragma once
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#if defined(OS_POSIX)
+#include <list>
+#include <utility>
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#endif
+
+namespace base {
+
+// This replaces INFINITE from Win32
+static const int kNoTimeout = -1;
+
+class TimeDelta;
+
+// A WaitableEvent can be a useful thread synchronization tool when you want to
+// allow one thread to wait for another thread to finish some work. For
+// non-Windows systems, this can only be used from within a single address
+// space.
+//
+// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to
+// protect a simple boolean value.  However, if you find yourself using a
+// WaitableEvent in conjunction with a Lock to wait for a more complex state
+// change (e.g., for an item to be added to a queue), then you should probably
+// be using a ConditionVariable instead of a WaitableEvent.
+//
+// NOTE: On Windows, this class provides a subset of the functionality afforded
+// 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 BASE_EXPORT 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
+  // system automatically resets the event state to non-signaled after a single
+  // waiting thread has been released.
+  WaitableEvent(bool manual_reset, bool initially_signaled);
+
+#if defined(OS_WIN)
+  // Create a WaitableEvent from an Event HANDLE which has already been
+  // created. This objects takes ownership of the HANDLE and will close it when
+  // deleted.
+  explicit WaitableEvent(HANDLE event_handle);
+
+  // Releases ownership of the handle from this object.
+  HANDLE Release();
+#endif
+
+  ~WaitableEvent();
+
+  // Put the event in the un-signaled state.
+  void Reset();
+
+  // Put the event in the signaled state.  Causing any thread blocked on Wait
+  // to be woken up.
+  void Signal();
+
+  // Returns true if the event is in the signaled state, else false.  If this
+  // is not a manual reset event, then this test will cause a reset.
+  bool IsSignaled();
+
+  // Wait indefinitely for the event to be signaled.  Returns true if the event
+  // was signaled, else false is returned to indicate that waiting failed.
+  bool Wait();
+
+  // Wait up until max_time has passed for the event to be signaled.  Returns
+  // true if the event was signaled.  If this method returns false, then it
+  // does not necessarily mean that max_time was exceeded.
+  bool TimedWait(const TimeDelta& max_time);
+
+#if defined(OS_WIN)
+  HANDLE handle() const { return handle_; }
+#endif
+
+  // Wait, synchronously, on multiple events.
+  //   waitables: an array of WaitableEvent pointers
+  //   count: the number of elements in @waitables
+  //
+  // returns: the index of a WaitableEvent which has been signaled.
+  //
+  // You MUST NOT delete any of the WaitableEvent objects while this wait is
+  // happening.
+  static size_t WaitMany(WaitableEvent** waitables, size_t count);
+
+  // For asynchronous waiting, see WaitableEventWatcher
+
+  // This is a private helper class. It's here because it's used by friends of
+  // this class (such as WaitableEventWatcher) to be able to enqueue elements
+  // of the wait-list
+  class Waiter {
+   public:
+    // Signal the waiter to wake up.
+    //
+    // Consider the case of a Waiter which is in multiple WaitableEvent's
+    // wait-lists. Each WaitableEvent is automatic-reset and two of them are
+    // signaled at the same time. Now, each will wake only the first waiter in
+    // the wake-list before resetting. However, if those two waiters happen to
+    // be the same object (as can happen if another thread didn't have a chance
+    // to dequeue the waiter from the other wait-list in time), two auto-resets
+    // will have happened, but only one waiter has been signaled!
+    //
+    // Because of this, a Waiter may "reject" a wake by returning false. In
+    // this case, the auto-reset WaitableEvent shouldn't act as if anything has
+    // been notified.
+    virtual bool Fire(WaitableEvent* signaling_event) = 0;
+
+    // Waiters may implement this in order to provide an extra condition for
+    // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the
+    // pointers match then this function is called as a final check. See the
+    // comments in ~Handle for why.
+    virtual bool Compare(void* tag) = 0;
+
+   protected:
+    virtual ~Waiter() {}
+  };
+
+ private:
+  friend class WaitableEventWatcher;
+
+#if defined(OS_WIN)
+  HANDLE handle_;
+#else
+  // On Windows, one can close a HANDLE which is currently being waited on. The
+  // MSDN documentation says that the resulting behaviour is 'undefined', but
+  // it doesn't crash. However, if we were to include the following members
+  // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an
+  // event which gets deleted. This mismatch has bitten us several times now,
+  // so we have a kernel of the WaitableEvent, which is reference counted.
+  // WaitableEventWatchers may then take a reference and thus match the Windows
+  // behaviour.
+  struct WaitableEventKernel :
+      public RefCountedThreadSafe<WaitableEventKernel> {
+   public:
+    WaitableEventKernel(bool manual_reset, bool initially_signaled);
+    virtual ~WaitableEventKernel();
+
+    bool Dequeue(Waiter* waiter, void* tag);
+
+    base::Lock lock_;
+    const bool manual_reset_;
+    bool signaled_;
+    std::list<Waiter*> waiters_;
+  };
+
+  typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
+
+  // When dealing with arrays of WaitableEvent*, we want to sort by the address
+  // of the WaitableEvent in order to have a globally consistent locking order.
+  // In that case we keep them, in sorted order, in an array of pairs where the
+  // second element is the index of the WaitableEvent in the original,
+  // unsorted, array.
+  static size_t EnqueueMany(WaiterAndIndex* waitables,
+                            size_t count, Waiter* waiter);
+
+  bool SignalAll();
+  bool SignalOne();
+  void Enqueue(Waiter* waiter);
+
+  scoped_refptr<WaitableEventKernel> kernel_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
+};
+
+}  // namespace base
+
+#endif  // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
diff --git a/base/template_util.h b/base/template_util.h
new file mode 100644 (file)
index 0000000..f19fb4b
--- /dev/null
@@ -0,0 +1,109 @@
+// 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_TEMPLATE_UTIL_H_
+#define BASE_TEMPLATE_UTIL_H_
+#pragma once
+
+#include <cstddef>  // For size_t.
+
+#include "build/build_config.h"
+
+namespace base {
+
+// template definitions from tr1
+
+template<class T, T v>
+struct integral_constant {
+  static const T value = v;
+  typedef T value_type;
+  typedef integral_constant<T, v> type;
+};
+
+template <class T, T v> const T integral_constant<T, v>::value;
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template <class T> struct is_pointer : false_type {};
+template <class T> struct is_pointer<T*> : true_type {};
+
+template <class T, class U> struct is_same : public false_type {};
+template <class T> struct is_same<T,T> : true_type {};
+
+template<class> struct is_array : public false_type {};
+template<class T, size_t n> struct is_array<T[n]> : public true_type {};
+template<class T> struct is_array<T[]> : public true_type {};
+
+template <class T> struct is_non_const_reference : false_type {};
+template <class T> struct is_non_const_reference<T&> : true_type {};
+template <class T> struct is_non_const_reference<const T&> : false_type {};
+
+template <class T> struct is_void : false_type {};
+template <> struct is_void<void> : true_type {};
+
+namespace internal {
+
+// Types YesType and NoType are guaranteed such that sizeof(YesType) <
+// sizeof(NoType).
+typedef char YesType;
+
+struct NoType {
+  YesType dummy[2];
+};
+
+// This class is an implementation detail for is_convertible, and you
+// don't need to know how it works to use is_convertible. For those
+// who care: we declare two different functions, one whose argument is
+// of type To and one with a variadic argument list. We give them
+// return types of different size, so we can use sizeof to trick the
+// compiler into telling us which function it would have chosen if we
+// had called it with an argument of type From.  See Alexandrescu's
+// _Modern C++ Design_ for more details on this sort of trick.
+
+struct ConvertHelper {
+  template <typename To>
+  static YesType Test(To);
+
+  template <typename To>
+  static NoType Test(...);
+
+  template <typename From>
+  static From Create();
+};
+
+// Used to determine if a type is a struct/union/class. Inspired by Boost's
+// is_class type_trait implementation.
+struct IsClassHelper {
+  template <typename C>
+  static YesType Test(void(C::*)(void));
+
+  template <typename C>
+  static NoType Test(...);
+};
+
+}  // namespace internal
+
+// Inherits from true_type if From is convertible to To, false_type otherwise.
+//
+// Note that if the type is convertible, this will be a true_type REGARDLESS
+// of whether or not the conversion would emit a warning.
+template <typename From, typename To>
+struct is_convertible
+    : integral_constant<bool,
+                        sizeof(internal::ConvertHelper::Test<To>(
+                                   internal::ConvertHelper::Create<From>())) ==
+                        sizeof(internal::YesType)> {
+};
+
+template <typename T>
+struct is_class
+    : integral_constant<bool,
+                        sizeof(internal::IsClassHelper::Test<T>(0)) ==
+                            sizeof(internal::YesType)> {
+};
+
+}  // namespace base
+
+#endif  // BASE_TEMPLATE_UTIL_H_
diff --git a/base/third_party/dynamic_annotations/LICENSE b/base/third_party/dynamic_annotations/LICENSE
new file mode 100644 (file)
index 0000000..5c581a9
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (c) 2008-2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Kostya Serebryany
+ */
diff --git a/base/third_party/dynamic_annotations/README.chromium b/base/third_party/dynamic_annotations/README.chromium
new file mode 100644 (file)
index 0000000..f78a982
--- /dev/null
@@ -0,0 +1,11 @@
+Name: dynamic annotations
+URL: http://code.google.com/p/data-race-test/wiki/DynamicAnnotations
+
+One header and one source file (dynamic_annotations.h and dynamic_annotations.c)
+in this directory define runtime macros useful for annotating synchronization
+utilities and benign data races so data race detectors can handle Chromium code
+with better precision.
+
+These files were taken from
+http://code.google.com/p/data-race-test/source/browse/?r=2062#svn/trunk/dynamic_annotations
+The files are covered under BSD license as described within the files.
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.c b/base/third_party/dynamic_annotations/dynamic_annotations.c
new file mode 100644 (file)
index 0000000..e7d44f4
--- /dev/null
@@ -0,0 +1,257 @@
+/* Copyright (c) 2011, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef _MSC_VER
+# include <windows.h>
+#endif
+
+#ifdef __cplusplus
+# error "This file should be built as pure C to avoid name mangling"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+
+#ifdef __GNUC__
+/* valgrind.h uses gcc extensions so it won't build with other compilers */
+# include "base/third_party/valgrind/valgrind.h"
+#endif
+
+/* Each function is empty and called (via a macro) only in debug mode.
+   The arguments are captured by dynamic tools at runtime. */
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 1
+
+/* Identical code folding(-Wl,--icf=all) countermeasures.
+   This makes all Annotate* functions different, which prevents the linker from
+   folding them. */
+#ifdef __COUNTER__
+#define DYNAMIC_ANNOTATIONS_IMPL \
+  volatile short lineno = (__LINE__ << 8) + __COUNTER__; (void)lineno;
+#else
+#define DYNAMIC_ANNOTATIONS_IMPL \
+  volatile short lineno = (__LINE__ << 8); (void)lineno;
+#endif
+
+/* WARNING: always add new annotations to the end of the list.
+   Otherwise, lineno (see above) numbers for different Annotate* functions may
+   conflict. */
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(
+    const char *file, int line, const volatile void *lock)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(
+    const char *file, int line, const volatile void *lock)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(
+    const char *file, int line, const volatile void *lock, long is_w)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(
+    const char *file, int line, const volatile void *lock, long is_w)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(
+    const char *file, int line, const volatile void *barrier, long count,
+    long reinitialization_allowed)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(
+    const char *file, int line, const volatile void *barrier)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(
+    const char *file, int line, const volatile void *barrier)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(
+    const char *file, int line, const volatile void *barrier)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(
+    const char *file, int line, const volatile void *cv,
+    const volatile void *lock)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(
+    const char *file, int line, const volatile void *cv)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(
+    const char *file, int line, const volatile void *cv)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)(
+    const char *file, int line, const volatile void *obj)
+{DYNAMIC_ANNOTATIONS_IMPL};
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)(
+    const char *file, int line, const volatile void *obj)
+{DYNAMIC_ANNOTATIONS_IMPL};
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(
+    const char *file, int line, const volatile void *address, long size)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(
+    const char *file, int line, const volatile void *address, long size)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(
+    const char *file, int line, const volatile void *pcq)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(
+    const char *file, int line, const volatile void *pcq)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(
+    const char *file, int line, const volatile void *pcq)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(
+    const char *file, int line, const volatile void *pcq)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(
+    const char *file, int line, const volatile void *mem, long size)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(
+    const char *file, int line, const volatile void *mem, long size,
+    const char *description)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(
+    const char *file, int line, const volatile void *mu)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(
+    const char *file, int line, const volatile void *mu)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(
+    const char *file, int line, const volatile void *arg)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(
+    const char *file, int line, const char *name)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(
+    const char *file, int line, int enable)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(
+    const char *file, int line, const volatile void *arg)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(
+    const char *file, int line)
+{DYNAMIC_ANNOTATIONS_IMPL}
+
+#endif  /* DYNAMIC_ANNOTATIONS_ENABLED == 1 */
+
+#if DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1
+static int GetRunningOnValgrind(void) {
+#ifdef RUNNING_ON_VALGRIND
+  if (RUNNING_ON_VALGRIND) return 1;
+#endif
+
+#ifndef _MSC_VER
+  char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
+  if (running_on_valgrind_str) {
+    return strcmp(running_on_valgrind_str, "0") != 0;
+  }
+#else
+  /* Visual Studio issues warnings if we use getenv,
+   * so we use GetEnvironmentVariableA instead.
+   */
+  char value[100] = "1";
+  int res = GetEnvironmentVariableA("RUNNING_ON_VALGRIND",
+                                    value, sizeof(value));
+  /* value will remain "1" if res == 0 or res >= sizeof(value). The latter
+   * can happen only if the given value is long, in this case it can't be "0".
+   */
+  if (res > 0 && strcmp(value, "0") != 0)
+    return 1;
+#endif
+  return 0;
+}
+
+/* See the comments in dynamic_annotations.h */
+int RunningOnValgrind(void) {
+  static volatile int running_on_valgrind = -1;
+  /* C doesn't have thread-safe initialization of statics, and we
+     don't want to depend on pthread_once here, so hack it. */
+  int local_running_on_valgrind = running_on_valgrind;
+  if (local_running_on_valgrind == -1)
+    running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
+  return local_running_on_valgrind;
+}
+
+#endif /* DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 */
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.gyp b/base/third_party/dynamic_annotations/dynamic_annotations.gyp
new file mode 100644 (file)
index 0000000..47334d8
--- /dev/null
@@ -0,0 +1,45 @@
+# 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'dynamic_annotations',
+      'type': 'static_library',
+      'include_dirs': [
+        '../../../',
+      ],
+      'sources': [
+        'dynamic_annotations.c',
+        'dynamic_annotations.h',
+      ],
+    },
+  ],
+  'conditions': [
+    ['OS == "win"', {
+      'targets': [
+        {
+          'target_name': 'dynamic_annotations_win64',
+          'type': 'static_library',
+          # We can't use dynamic_annotations target for win64 build since it is
+          # a 32-bit library.
+          # TODO(gregoryd): merge with dynamic_annotations when
+          # the win32/64 targets are merged.
+          'include_dirs': [
+              '../../../',
+          ],
+          'sources': [
+            'dynamic_annotations.c',
+            'dynamic_annotations.h',
+          ],
+          'configurations': {
+            'Common_Base': {
+              'msvs_target_platform': 'x64',
+            },
+          },
+        },
+      ],
+    }],
+  ],
+}
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.h b/base/third_party/dynamic_annotations/dynamic_annotations.h
new file mode 100644 (file)
index 0000000..8d7f052
--- /dev/null
@@ -0,0 +1,595 @@
+/* Copyright (c) 2011, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* This file defines dynamic annotations for use with dynamic analysis
+   tool such as valgrind, PIN, etc.
+
+   Dynamic annotation is a source code annotation that affects
+   the generated code (that is, the annotation is not a comment).
+   Each such annotation is attached to a particular
+   instruction and/or to a particular object (address) in the program.
+
+   The annotations that should be used by users are macros in all upper-case
+   (e.g., ANNOTATE_NEW_MEMORY).
+
+   Actual implementation of these macros may differ depending on the
+   dynamic analysis tool being used.
+
+   See http://code.google.com/p/data-race-test/  for more information.
+
+   This file supports the following dynamic analysis tools:
+   - None (DYNAMIC_ANNOTATIONS_ENABLED is not defined or zero).
+      Macros are defined empty.
+   - ThreadSanitizer, Helgrind, DRD (DYNAMIC_ANNOTATIONS_ENABLED is 1).
+      Macros are defined as calls to non-inlinable empty functions
+      that are intercepted by Valgrind. */
+
+#ifndef __DYNAMIC_ANNOTATIONS_H__
+#define __DYNAMIC_ANNOTATIONS_H__
+
+#ifndef DYNAMIC_ANNOTATIONS_PREFIX
+# define DYNAMIC_ANNOTATIONS_PREFIX
+#endif
+
+#ifndef DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND
+# define DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND 1
+#endif
+
+#ifdef DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK
+# ifdef __GNUC__
+#  define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak))
+# else
+/* TODO(glider): for Windows support we may want to change this macro in order
+   to prepend __declspec(selectany) to the annotations' declarations. */
+#  error weak annotations are not supported for your compiler
+# endif
+#else
+# define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK
+#endif
+
+/* The following preprocessor magic prepends the value of
+   DYNAMIC_ANNOTATIONS_PREFIX to annotation function names. */
+#define DYNAMIC_ANNOTATIONS_GLUE0(A, B) A##B
+#define DYNAMIC_ANNOTATIONS_GLUE(A, B) DYNAMIC_ANNOTATIONS_GLUE0(A, B)
+#define DYNAMIC_ANNOTATIONS_NAME(name) \
+  DYNAMIC_ANNOTATIONS_GLUE(DYNAMIC_ANNOTATIONS_PREFIX, name)
+
+#ifndef DYNAMIC_ANNOTATIONS_ENABLED
+# define DYNAMIC_ANNOTATIONS_ENABLED 0
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0
+
+  /* -------------------------------------------------------------
+     Annotations useful when implementing condition variables such as CondVar,
+     using conditional critical sections (Await/LockWhen) and when constructing
+     user-defined synchronization mechanisms.
+
+     The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can
+     be used to define happens-before arcs in user-defined synchronization
+     mechanisms:  the race detector will infer an arc from the former to the
+     latter when they share the same argument pointer.
+
+     Example 1 (reference counting):
+
+     void Unref() {
+       ANNOTATE_HAPPENS_BEFORE(&refcount_);
+       if (AtomicDecrementByOne(&refcount_) == 0) {
+         ANNOTATE_HAPPENS_AFTER(&refcount_);
+         delete this;
+       }
+     }
+
+     Example 2 (message queue):
+
+     void MyQueue::Put(Type *e) {
+       MutexLock lock(&mu_);
+       ANNOTATE_HAPPENS_BEFORE(e);
+       PutElementIntoMyQueue(e);
+     }
+
+     Type *MyQueue::Get() {
+       MutexLock lock(&mu_);
+       Type *e = GetElementFromMyQueue();
+       ANNOTATE_HAPPENS_AFTER(e);
+       return e;
+     }
+
+     Note: when possible, please use the existing reference counting and message
+     queue implementations instead of inventing new ones. */
+
+  /* Report that wait on the condition variable at address "cv" has succeeded
+     and the lock at address "lock" is held. */
+  #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, lock)
+
+  /* Report that wait on the condition variable at "cv" has succeeded.  Variant
+     w/o lock. */
+  #define ANNOTATE_CONDVAR_WAIT(cv) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, NULL)
+
+  /* Report that we are about to signal on the condition variable at address
+     "cv". */
+  #define ANNOTATE_CONDVAR_SIGNAL(cv) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(__FILE__, __LINE__, cv)
+
+  /* Report that we are about to signal_all on the condition variable at address
+     "cv". */
+  #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(__FILE__, __LINE__, cv)
+
+  /* Annotations for user-defined synchronization mechanisms. */
+  #define ANNOTATE_HAPPENS_BEFORE(obj) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)(__FILE__, __LINE__, obj)
+  #define ANNOTATE_HAPPENS_AFTER(obj) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)(__FILE__, __LINE__, obj)
+
+  /* DEPRECATED. Don't use it. */
+  #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(__FILE__, __LINE__, \
+        pointer, size)
+
+  /* DEPRECATED. Don't use it. */
+  #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(__FILE__, __LINE__, \
+        pointer, size)
+
+  /* DEPRECATED. Don't use it. */
+  #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size)   \
+    do {                                              \
+      ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \
+      ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size);   \
+    } while (0)
+
+  /* Instruct the tool to create a happens-before arc between mu->Unlock() and
+     mu->Lock(). This annotation may slow down the race detector and hide real
+     races. Normally it is used only when it would be difficult to annotate each
+     of the mutex's critical sections individually using the annotations above.
+     This annotation makes sense only for hybrid race detectors. For pure
+     happens-before detectors this is a no-op. For more details see
+     http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */
+  #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \
+        mu)
+
+  /* Opposite to ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX.
+     Instruct the tool to NOT create h-b arcs between Unlock and Lock, even in
+     pure happens-before mode. For a hybrid mode this is a no-op. */
+  #define ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(mu) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(__FILE__, __LINE__, mu)
+
+  /* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
+  #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \
+        mu)
+
+  /* -------------------------------------------------------------
+     Annotations useful when defining memory allocators, or when memory that
+     was protected in one way starts to be protected in another. */
+
+  /* Report that a new memory at "address" of size "size" has been allocated.
+     This might be used when the memory has been retrieved from a free list and
+     is about to be reused, or when a the locking discipline for a variable
+     changes. */
+  #define ANNOTATE_NEW_MEMORY(address, size) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(__FILE__, __LINE__, address, \
+        size)
+
+  /* -------------------------------------------------------------
+     Annotations useful when defining FIFO queues that transfer data between
+     threads. */
+
+  /* Report that the producer-consumer queue (such as ProducerConsumerQueue) at
+     address "pcq" has been created.  The ANNOTATE_PCQ_* annotations
+     should be used only for FIFO queues.  For non-FIFO queues use
+     ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
+  #define ANNOTATE_PCQ_CREATE(pcq) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(__FILE__, __LINE__, pcq)
+
+  /* Report that the queue at address "pcq" is about to be destroyed. */
+  #define ANNOTATE_PCQ_DESTROY(pcq) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(__FILE__, __LINE__, pcq)
+
+  /* Report that we are about to put an element into a FIFO queue at address
+     "pcq". */
+  #define ANNOTATE_PCQ_PUT(pcq) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(__FILE__, __LINE__, pcq)
+
+  /* Report that we've just got an element from a FIFO queue at address
+     "pcq". */
+  #define ANNOTATE_PCQ_GET(pcq) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(__FILE__, __LINE__, pcq)
+
+  /* -------------------------------------------------------------
+     Annotations that suppress errors.  It is usually better to express the
+     program's synchronization using the other annotations, but these can
+     be used when all else fails. */
+
+  /* Report that we may have a benign race at "pointer", with size
+     "sizeof(*(pointer))". "pointer" must be a non-void* pointer.  Insert at the
+     point where "pointer" has been allocated, preferably close to the point
+     where the race happens.  See also ANNOTATE_BENIGN_RACE_STATIC. */
+  #define ANNOTATE_BENIGN_RACE(pointer, description) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \
+        pointer, sizeof(*(pointer)), description)
+
+  /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
+     the memory range [address, address+size). */
+  #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \
+        address, size, description)
+
+  /* Request the analysis tool to ignore all reads in the current thread
+     until ANNOTATE_IGNORE_READS_END is called.
+     Useful to ignore intentional racey reads, while still checking
+     other reads and all writes.
+     See also ANNOTATE_UNPROTECTED_READ. */
+  #define ANNOTATE_IGNORE_READS_BEGIN() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
+
+  /* Stop ignoring reads. */
+  #define ANNOTATE_IGNORE_READS_END() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
+
+  /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
+  #define ANNOTATE_IGNORE_WRITES_BEGIN() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
+
+  /* Stop ignoring writes. */
+  #define ANNOTATE_IGNORE_WRITES_END() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
+
+  /* Start ignoring all memory accesses (reads and writes). */
+  #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+    do {\
+      ANNOTATE_IGNORE_READS_BEGIN();\
+      ANNOTATE_IGNORE_WRITES_BEGIN();\
+    }while(0)\
+
+  /* Stop ignoring all memory accesses. */
+  #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+    do {\
+      ANNOTATE_IGNORE_WRITES_END();\
+      ANNOTATE_IGNORE_READS_END();\
+    }while(0)\
+
+  /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore synchronization events:
+     RWLOCK* and CONDVAR*. */
+  #define ANNOTATE_IGNORE_SYNC_BEGIN() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(__FILE__, __LINE__)
+
+  /* Stop ignoring sync events. */
+  #define ANNOTATE_IGNORE_SYNC_END() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(__FILE__, __LINE__)
+
+
+  /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
+     This annotation could be useful if you want to skip expensive race analysis
+     during some period of program execution, e.g. during initialization. */
+  #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(__FILE__, __LINE__, \
+        enable)
+
+  /* -------------------------------------------------------------
+     Annotations useful for debugging. */
+
+  /* Request to trace every access to "address". */
+  #define ANNOTATE_TRACE_MEMORY(address) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(__FILE__, __LINE__, address)
+
+  /* Report the current thread name to a race detector. */
+  #define ANNOTATE_THREAD_NAME(name) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(__FILE__, __LINE__, name)
+
+  /* -------------------------------------------------------------
+     Annotations useful when implementing locks.  They are not
+     normally needed by modules that merely use locks.
+     The "lock" argument is a pointer to the lock object. */
+
+  /* Report that a lock has been created at address "lock". */
+  #define ANNOTATE_RWLOCK_CREATE(lock) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
+
+  /* Report that the lock at address "lock" is about to be destroyed. */
+  #define ANNOTATE_RWLOCK_DESTROY(lock) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
+
+  /* Report that the lock at address "lock" has been acquired.
+     is_w=1 for writer lock, is_w=0 for reader lock. */
+  #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(__FILE__, __LINE__, lock, \
+        is_w)
+
+  /* Report that the lock at address "lock" is about to be released. */
+  #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(__FILE__, __LINE__, lock, \
+        is_w)
+
+  /* -------------------------------------------------------------
+     Annotations useful when implementing barriers.  They are not
+     normally needed by modules that merely use barriers.
+     The "barrier" argument is a pointer to the barrier object. */
+
+  /* Report that the "barrier" has been initialized with initial "count".
+   If 'reinitialization_allowed' is true, initialization is allowed to happen
+   multiple times w/o calling barrier_destroy() */
+  #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(__FILE__, __LINE__, barrier, \
+        count, reinitialization_allowed)
+
+  /* Report that we are about to enter barrier_wait("barrier"). */
+  #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(__FILE__, __LINE__, \
+        barrier)
+
+  /* Report that we just exited barrier_wait("barrier"). */
+  #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(__FILE__, __LINE__, \
+        barrier)
+
+  /* Report that the "barrier" has been destroyed. */
+  #define ANNOTATE_BARRIER_DESTROY(barrier) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(__FILE__, __LINE__, \
+        barrier)
+
+  /* -------------------------------------------------------------
+     Annotations useful for testing race detectors. */
+
+  /* Report that we expect a race on the variable at "address".
+     Use only in unit tests for a race detector. */
+  #define ANNOTATE_EXPECT_RACE(address, description) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(__FILE__, __LINE__, address, \
+        description)
+
+  #define ANNOTATE_FLUSH_EXPECTED_RACES() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(__FILE__, __LINE__)
+
+  /* A no-op. Insert where you like to test the interceptors. */
+  #define ANNOTATE_NO_OP(arg) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(__FILE__, __LINE__, arg)
+
+  /* Force the race detector to flush its state. The actual effect depends on
+   * the implementation of the detector. */
+  #define ANNOTATE_FLUSH_STATE() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(__FILE__, __LINE__)
+
+
+#else  /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+
+  #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
+  #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
+  #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
+  #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
+  #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */
+  #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */
+  #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */
+  #define ANNOTATE_BARRIER_DESTROY(barrier) /* empty */
+  #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */
+  #define ANNOTATE_CONDVAR_WAIT(cv) /* empty */
+  #define ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */
+  #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */
+  #define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
+  #define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
+  #define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */
+  #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size)  /* empty */
+  #define ANNOTATE_SWAP_MEMORY_RANGE(address, size)  /* empty */
+  #define ANNOTATE_PCQ_CREATE(pcq) /* empty */
+  #define ANNOTATE_PCQ_DESTROY(pcq) /* empty */
+  #define ANNOTATE_PCQ_PUT(pcq) /* empty */
+  #define ANNOTATE_PCQ_GET(pcq) /* empty */
+  #define ANNOTATE_NEW_MEMORY(address, size) /* empty */
+  #define ANNOTATE_EXPECT_RACE(address, description) /* empty */
+  #define ANNOTATE_FLUSH_EXPECTED_RACES(address, description) /* empty */
+  #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
+  #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
+  #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */
+  #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */
+  #define ANNOTATE_TRACE_MEMORY(arg) /* empty */
+  #define ANNOTATE_THREAD_NAME(name) /* empty */
+  #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
+  #define ANNOTATE_IGNORE_READS_END() /* empty */
+  #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
+  #define ANNOTATE_IGNORE_WRITES_END() /* empty */
+  #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
+  #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
+  #define ANNOTATE_IGNORE_SYNC_BEGIN() /* empty */
+  #define ANNOTATE_IGNORE_SYNC_END() /* empty */
+  #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
+  #define ANNOTATE_NO_OP(arg) /* empty */
+  #define ANNOTATE_FLUSH_STATE() /* empty */
+
+#endif  /* DYNAMIC_ANNOTATIONS_ENABLED */
+
+/* Use the macros above rather than using these functions directly. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(
+    const char *file, int line,
+    const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(
+    const char *file, int line,
+    const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(
+    const char *file, int line,
+    const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(
+    const char *file, int line,
+    const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(
+    const char *file, int line, const volatile void *barrier, long count,
+    long reinitialization_allowed) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(
+    const char *file, int line,
+    const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(
+    const char *file, int line,
+    const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(
+    const char *file, int line,
+    const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(
+    const char *file, int line, const volatile void *cv,
+    const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(
+    const char *file, int line,
+    const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(
+    const char *file, int line,
+    const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)(
+    const char *file, int line,
+    const volatile void *obj) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)(
+    const char *file, int line,
+    const volatile void *obj) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(
+    const char *file, int line,
+    const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(
+    const char *file, int line,
+    const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(
+    const char *file, int line,
+    const volatile void *mem, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(
+    const char *file, int line, const volatile void *mem, long size,
+    const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(
+    const char *file, int line,
+    const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(
+    const char *file, int line,
+    const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(
+    const char *file, int line,
+    const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(
+    const char *file, int line,
+    const char *name) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(
+    const char *file, int line, int enable) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(
+    const char *file, int line,
+    const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+
+#if DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1
+/* Return non-zero value if running under valgrind.
+
+  If "valgrind.h" is included into dynamic_annotations.c,
+  the regular valgrind mechanism will be used.
+  See http://valgrind.org/docs/manual/manual-core-adv.html about
+  RUNNING_ON_VALGRIND and other valgrind "client requests".
+  The file "valgrind.h" may be obtained by doing
+     svn co svn://svn.valgrind.org/valgrind/trunk/include
+
+  If for some reason you can't use "valgrind.h" or want to fake valgrind,
+  there are two ways to make this function return non-zero:
+    - Use environment variable: export RUNNING_ON_VALGRIND=1
+    - Make your tool intercept the function RunningOnValgrind() and
+      change its return value.
+ */
+int RunningOnValgrind(void) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+#endif /* DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
+
+  /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+
+     Instead of doing
+        ANNOTATE_IGNORE_READS_BEGIN();
+        ... = x;
+        ANNOTATE_IGNORE_READS_END();
+     one can use
+        ... = ANNOTATE_UNPROTECTED_READ(x); */
+  template <class T>
+  inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) {
+    ANNOTATE_IGNORE_READS_BEGIN();
+    T res = x;
+    ANNOTATE_IGNORE_READS_END();
+    return res;
+  }
+  /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
+  #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)        \
+    namespace {                                                       \
+      class static_var ## _annotator {                                \
+       public:                                                        \
+        static_var ## _annotator() {                                  \
+          ANNOTATE_BENIGN_RACE_SIZED(&static_var,                     \
+                                      sizeof(static_var),             \
+            # static_var ": " description);                           \
+        }                                                             \
+      };                                                              \
+      static static_var ## _annotator the ## static_var ## _annotator;\
+    }
+#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+
+  #define ANNOTATE_UNPROTECTED_READ(x) (x)
+  #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)  /* empty */
+
+#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+
+#endif  /* __DYNAMIC_ANNOTATIONS_H__ */
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h
new file mode 100644 (file)
index 0000000..8382bbe
--- /dev/null
@@ -0,0 +1,115 @@
+// 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.
+
+// WARNING: You should *NOT* be using this class directly.  PlatformThread is
+// the low-level platform-specific abstraction to the OS's threading interface.
+// You should instead be using a message-loop driven Thread, see thread.h.
+
+#ifndef BASE_THREADING_PLATFORM_THREAD_H_
+#define BASE_THREADING_PLATFORM_THREAD_H_
+#pragma once
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_POSIX)
+#include <pthread.h>
+#if defined(OS_MACOSX)
+#include <mach/mach.h>
+#else  // OS_POSIX && !OS_MACOSX
+#include <unistd.h>
+#endif
+#endif
+
+namespace base {
+
+// PlatformThreadHandle should not be assumed to be a numeric type, since the
+// standard intends to allow pthread_t to be a structure.  This means you
+// should not initialize it to a value, like 0.  If it's a member variable, the
+// constructor can safely "value initialize" using () in the initializer list.
+#if defined(OS_WIN)
+typedef DWORD PlatformThreadId;
+typedef void* PlatformThreadHandle;  // HANDLE
+const PlatformThreadHandle kNullThreadHandle = NULL;
+#elif defined(OS_POSIX)
+typedef pthread_t PlatformThreadHandle;
+const PlatformThreadHandle kNullThreadHandle = 0;
+#if defined(OS_MACOSX)
+typedef mach_port_t PlatformThreadId;
+#else  // OS_POSIX && !OS_MACOSX
+typedef pid_t PlatformThreadId;
+#endif
+#endif
+
+const PlatformThreadId kInvalidThreadId = 0;
+
+// Valid values for SetThreadPriority()
+enum ThreadPriority{
+  kThreadPriority_Normal,
+  // Suitable for low-latency, glitch-resistant audio.
+  kThreadPriority_RealtimeAudio
+};
+
+// A namespace for low-level thread functions.
+class BASE_EXPORT PlatformThread {
+ public:
+  // Implement this interface to run code on a background thread.  Your
+  // ThreadMain method will be called on the newly created thread.
+  class BASE_EXPORT Delegate {
+   public:
+    virtual ~Delegate() {}
+    virtual void ThreadMain() = 0;
+  };
+
+  // Gets the current thread id, which may be useful for logging purposes.
+  static PlatformThreadId CurrentId();
+
+  // Yield the current thread so another thread can be scheduled.
+  static void YieldCurrentThread();
+
+  // Sleeps for the specified duration (units are milliseconds).
+  static void Sleep(int duration_ms);
+
+  // Sets the thread name visible to debuggers/tools. This has no effect
+  // otherwise. This name pointer is not copied internally. Thus, it must stay
+  // valid until the thread ends.
+  static void SetName(const char* name);
+
+  // Gets the thread name, if previously set by SetName.
+  static const char* GetName();
+
+  // Creates a new thread.  The |stack_size| parameter can be 0 to indicate
+  // that the default stack size should be used.  Upon success,
+  // |*thread_handle| will be assigned a handle to the newly created thread,
+  // and |delegate|'s ThreadMain method will be executed on the newly created
+  // thread.
+  // NOTE: When you are done with the thread handle, you must call Join to
+  // release system resources associated with the thread.  You must ensure that
+  // the Delegate object outlives the thread.
+  static bool Create(size_t stack_size, Delegate* delegate,
+                     PlatformThreadHandle* thread_handle);
+
+  // CreateNonJoinable() does the same thing as Create() except the thread
+  // cannot be Join()'d.  Therefore, it also does not output a
+  // PlatformThreadHandle.
+  static bool CreateNonJoinable(size_t stack_size, Delegate* delegate);
+
+  // Joins with a thread created via the Create function.  This function blocks
+  // the caller until the designated thread exits.  This will invalidate
+  // |thread_handle|.
+  static void Join(PlatformThreadHandle thread_handle);
+
+  static void SetThreadPriority(PlatformThreadHandle handle,
+                                ThreadPriority priority);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_PLATFORM_THREAD_H_
diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc
new file mode 100644 (file)
index 0000000..c924a16
--- /dev/null
@@ -0,0 +1,262 @@
+// 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/threading/platform_thread.h"
+
+#include <errno.h>
+#include <sched.h>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/safe_strerror_posix.h"
+#include "base/threading/thread_local.h"
+#include "base/threading/thread_restrictions.h"
+
+#if defined(OS_MACOSX)
+#include <mach/mach.h>
+#include <sys/resource.h>
+#include <algorithm>
+#endif
+
+#if defined(OS_LINUX)
+#include <dlfcn.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#endif
+
+#if defined(OS_NACL)
+#include <sys/nacl_syscalls.h>
+#endif
+
+namespace base {
+
+#if defined(OS_MACOSX)
+void InitThreading();
+#endif
+
+namespace {
+
+static ThreadLocalPointer<char> current_thread_name;
+
+struct ThreadParams {
+  PlatformThread::Delegate* delegate;
+  bool joinable;
+};
+
+void* ThreadFunc(void* params) {
+  ThreadParams* thread_params = static_cast<ThreadParams*>(params);
+  PlatformThread::Delegate* delegate = thread_params->delegate;
+  if (!thread_params->joinable)
+    base::ThreadRestrictions::SetSingletonAllowed(false);
+  delete thread_params;
+  delegate->ThreadMain();
+#if defined(OS_ANDROID)
+  base::android::DetachFromVM();
+#endif
+  return NULL;
+}
+
+bool CreateThread(size_t stack_size, bool joinable,
+                  PlatformThread::Delegate* delegate,
+                  PlatformThreadHandle* thread_handle) {
+#if defined(OS_MACOSX)
+  base::InitThreading();
+#endif  // OS_MACOSX
+
+  bool success = false;
+  pthread_attr_t attributes;
+  pthread_attr_init(&attributes);
+
+  // Pthreads are joinable by default, so only specify the detached attribute if
+  // the thread should be non-joinable.
+  if (!joinable) {
+    pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
+  }
+
+#if defined(OS_MACOSX)
+  // The Mac OS X default for a pthread stack size is 512kB.
+  // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses
+  // DEFAULT_STACK_SIZE for this purpose.
+  //
+  // 512kB isn't quite generous enough for some deeply recursive threads that
+  // otherwise request the default stack size by specifying 0. Here, adopt
+  // glibc's behavior as on Linux, which is to use the current stack size
+  // limit (ulimit -s) as the default stack size. See
+  // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To
+  // avoid setting the limit below the Mac OS X default or the minimum usable
+  // stack size, these values are also considered. If any of these values
+  // can't be determined, or if stack size is unlimited (ulimit -s unlimited),
+  // stack_size is left at 0 to get the system default.
+  //
+  // Mac OS X normally only applies ulimit -s to the main thread stack. On
+  // contemporary OS X and Linux systems alike, this value is generally 8MB
+  // or in that neighborhood.
+  if (stack_size == 0) {
+    size_t default_stack_size;
+    struct rlimit stack_rlimit;
+    if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 &&
+        getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 &&
+        stack_rlimit.rlim_cur != RLIM_INFINITY) {
+      stack_size = std::max(std::max(default_stack_size,
+                                     static_cast<size_t>(PTHREAD_STACK_MIN)),
+                            static_cast<size_t>(stack_rlimit.rlim_cur));
+    }
+  }
+#endif  // OS_MACOSX
+
+  if (stack_size > 0)
+    pthread_attr_setstacksize(&attributes, stack_size);
+
+  ThreadParams* params = new ThreadParams;
+  params->delegate = delegate;
+  params->joinable = joinable;
+  success = !pthread_create(thread_handle, &attributes, ThreadFunc, params);
+
+  pthread_attr_destroy(&attributes);
+  if (!success)
+    delete params;
+  return success;
+}
+
+}  // namespace
+
+// static
+PlatformThreadId PlatformThread::CurrentId() {
+  // Pthreads doesn't have the concept of a thread ID, so we have to reach down
+  // into the kernel.
+#if defined(OS_MACOSX)
+  return mach_thread_self();
+#elif defined(OS_LINUX)
+  return syscall(__NR_gettid);
+#elif defined(OS_ANDROID)
+  return gettid();
+#elif defined(OS_FREEBSD)
+  // TODO(BSD): find a better thread ID
+  return reinterpret_cast<int64>(pthread_self());
+#elif defined(OS_NACL) || defined(OS_SOLARIS)
+  return pthread_self();
+#endif
+}
+
+// static
+void PlatformThread::YieldCurrentThread() {
+  sched_yield();
+}
+
+// static
+void PlatformThread::Sleep(int duration_ms) {
+  struct timespec sleep_time, remaining;
+
+  // Contains the portion of duration_ms >= 1 sec.
+  sleep_time.tv_sec = duration_ms / 1000;
+  duration_ms -= sleep_time.tv_sec * 1000;
+
+  // Contains the portion of duration_ms < 1 sec.
+  sleep_time.tv_nsec = duration_ms * 1000 * 1000;  // nanoseconds.
+
+  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
+    sleep_time = remaining;
+}
+
+// Linux SetName is currently disabled, as we need to distinguish between
+// helper threads (where it's ok to make this call) and the main thread
+// (where making this call renames our process, causing tools like killall
+// to stop working).
+#if 0 && defined(OS_LINUX)
+// static
+void PlatformThread::SetName(const char* name) {
+  // have to cast away const because ThreadLocalPointer does not support const
+  // void*
+  current_thread_name.Set(const_cast<char*>(name));
+
+  // http://0pointer.de/blog/projects/name-your-threads.html
+
+  // glibc recently added support for pthread_setname_np, but it's not
+  // commonly available yet.  So test for it at runtime.
+  int (*dynamic_pthread_setname_np)(pthread_t, const char*);
+  *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
+      dlsym(RTLD_DEFAULT, "pthread_setname_np");
+
+  if (dynamic_pthread_setname_np) {
+    // This limit comes from glibc, which gets it from the kernel
+    // (TASK_COMM_LEN).
+    const int kMaxNameLength = 15;
+    std::string shortened_name = std::string(name).substr(0, kMaxNameLength);
+    int err = dynamic_pthread_setname_np(pthread_self(),
+                                         shortened_name.c_str());
+    if (err < 0)
+      LOG(ERROR) << "pthread_setname_np: " << safe_strerror(err);
+  } else {
+    // Implementing this function without glibc is simple enough.  (We
+    // don't do the name length clipping as above because it will be
+    // truncated by the callee (see TASK_COMM_LEN above).)
+    int err = prctl(PR_SET_NAME, name);
+    if (err < 0)
+      PLOG(ERROR) << "prctl(PR_SET_NAME)";
+  }
+}
+#elif defined(OS_MACOSX)
+// Mac is implemented in platform_thread_mac.mm.
+#else
+// static
+void PlatformThread::SetName(const char* name) {
+  // have to cast away const because ThreadLocalPointer does not support const
+  // void*
+  current_thread_name.Set(const_cast<char*>(name));
+
+  // (This should be relatively simple to implement for the BSDs; I
+  // just don't have one handy to test the code on.)
+}
+#endif  // defined(OS_LINUX)
+
+
+#if !defined(OS_MACOSX)
+// Mac is implemented in platform_thread_mac.mm.
+// static
+const char* PlatformThread::GetName() {
+  return current_thread_name.Get();
+}
+#endif
+
+// static
+bool PlatformThread::Create(size_t stack_size, Delegate* delegate,
+                            PlatformThreadHandle* thread_handle) {
+  return CreateThread(stack_size, true /* joinable thread */,
+                      delegate, thread_handle);
+}
+
+// static
+bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
+  PlatformThreadHandle unused;
+
+  bool result = CreateThread(stack_size, false /* non-joinable thread */,
+                             delegate, &unused);
+  return result;
+}
+
+// static
+void PlatformThread::Join(PlatformThreadHandle thread_handle) {
+  // Joining another thread may block the current thread for a long time, since
+  // the thread referred to by |thread_handle| may still be running long-lived /
+  // blocking tasks.
+  base::ThreadRestrictions::AssertIOAllowed();
+  pthread_join(thread_handle, NULL);
+}
+
+#if !defined(OS_MACOSX)
+// Mac OS X uses lower-level mach APIs
+
+// static
+void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) {
+  // TODO(crogers): implement
+  NOTIMPLEMENTED();
+}
+#endif
+
+}  // namespace base
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
new file mode 100644 (file)
index 0000000..616aac8
--- /dev/null
@@ -0,0 +1,177 @@
+// 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/threading/thread.h"
+
+#include "base/lazy_instance.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "base/threading/thread_local.h"
+#include "base/synchronization/waitable_event.h"
+
+namespace base {
+
+namespace {
+
+// We use this thread-local variable to record whether or not a thread exited
+// because its Stop method was called.  This allows us to catch cases where
+// MessageLoop::Quit() is called directly, which is unexpected when using a
+// Thread to setup and run a MessageLoop.
+base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool(
+    base::LINKER_INITIALIZED);
+
+}  // namespace
+
+// This task is used to trigger the message loop to exit.
+class ThreadQuitTask : public Task {
+ public:
+  virtual void Run() {
+    MessageLoop::current()->Quit();
+    Thread::SetThreadWasQuitProperly(true);
+  }
+};
+
+// Used to pass data to ThreadMain.  This structure is allocated on the stack
+// from within StartWithOptions.
+struct Thread::StartupData {
+  // We get away with a const reference here because of how we are allocated.
+  const Thread::Options& options;
+
+  // Used to synchronize thread startup.
+  WaitableEvent event;
+
+  explicit StartupData(const Options& opt)
+      : options(opt),
+        event(false, false) {}
+};
+
+Thread::Thread(const char* name)
+    : started_(false),
+      stopping_(false),
+      startup_data_(NULL),
+      thread_(0),
+      message_loop_(NULL),
+      thread_id_(kInvalidThreadId),
+      name_(name) {
+}
+
+Thread::~Thread() {
+  Stop();
+}
+
+bool Thread::Start() {
+  return StartWithOptions(Options());
+}
+
+bool Thread::StartWithOptions(const Options& options) {
+  DCHECK(!message_loop_);
+
+  SetThreadWasQuitProperly(false);
+
+  StartupData startup_data(options);
+  startup_data_ = &startup_data;
+
+  if (!PlatformThread::Create(options.stack_size, this, &thread_)) {
+    DLOG(ERROR) << "failed to create thread";
+    startup_data_ = NULL;
+    return false;
+  }
+
+  // Wait for the thread to start and initialize message_loop_
+  startup_data.event.Wait();
+
+  // set it to NULL so we don't keep a pointer to some object on the stack.
+  startup_data_ = NULL;
+  started_ = true;
+
+  DCHECK(message_loop_);
+  return true;
+}
+
+void Thread::Stop() {
+  if (!thread_was_started())
+    return;
+
+  StopSoon();
+
+  // Wait for the thread to exit.
+  //
+  // TODO(darin): Unfortunately, we need to keep message_loop_ around until
+  // the thread exits.  Some consumers are abusing the API.  Make them stop.
+  //
+  PlatformThread::Join(thread_);
+
+  // The thread should NULL message_loop_ on exit.
+  DCHECK(!message_loop_);
+
+  // The thread no longer needs to be joined.
+  started_ = false;
+
+  stopping_ = false;
+}
+
+void Thread::StopSoon() {
+  // We should only be called on the same thread that started us.
+
+  // Reading thread_id_ without a lock can lead to a benign data race
+  // with ThreadMain, so we annotate it to stay silent under ThreadSanitizer.
+  DCHECK_NE(ANNOTATE_UNPROTECTED_READ(thread_id_), PlatformThread::CurrentId());
+
+  if (stopping_ || !message_loop_)
+    return;
+
+  stopping_ = true;
+  message_loop_->PostTask(FROM_HERE, new ThreadQuitTask());
+}
+
+void Thread::Run(MessageLoop* message_loop) {
+  message_loop->Run();
+}
+
+void Thread::SetThreadWasQuitProperly(bool flag) {
+  lazy_tls_bool.Pointer()->Set(flag);
+}
+
+bool Thread::GetThreadWasQuitProperly() {
+  bool quit_properly = true;
+#ifndef NDEBUG
+  quit_properly = lazy_tls_bool.Pointer()->Get();
+#endif
+  return quit_properly;
+}
+
+void Thread::ThreadMain() {
+  {
+    // The message loop for this thread.
+    MessageLoop message_loop(startup_data_->options.message_loop_type);
+
+    // Complete the initialization of our Thread object.
+    thread_id_ = PlatformThread::CurrentId();
+    PlatformThread::SetName(name_.c_str());
+    ANNOTATE_THREAD_NAME(name_.c_str());  // Tell the name to race detector.
+    message_loop.set_thread_name(name_);
+    message_loop_ = &message_loop;
+
+    // Let the thread do extra initialization.
+    // Let's do this before signaling we are started.
+    Init();
+
+    startup_data_->event.Signal();
+    // startup_data_ can't be touched anymore since the starting thread is now
+    // unlocked.
+
+    Run(message_loop_);
+
+    // Let the thread do extra cleanup.
+    CleanUp();
+
+    // Assert that MessageLoop::Quit was called by ThreadQuitTask.
+    DCHECK(GetThreadWasQuitProperly());
+
+    // We can't receive messages anymore.
+    message_loop_ = NULL;
+  }
+  thread_id_ = kInvalidThreadId;
+}
+
+}  // namespace base
diff --git a/base/threading/thread.h b/base/threading/thread.h
new file mode 100644 (file)
index 0000000..d7451ec
--- /dev/null
@@ -0,0 +1,191 @@
+// 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_THREAD_H_
+#define BASE_THREAD_H_
+#pragma once
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+// A simple thread abstraction that establishes a MessageLoop on a new thread.
+// The consumer uses the MessageLoop of the thread to cause code to execute on
+// the thread.  When this object is destroyed the thread is terminated.  All
+// pending tasks queued on the thread's message loop will run to completion
+// before the thread is terminated.
+//
+// After the thread is stopped, the destruction sequence is:
+//
+//  (1) Thread::CleanUp()
+//  (2) MessageLoop::~MessageLoop
+//  (3.b)    MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop
+class BASE_EXPORT Thread : PlatformThread::Delegate {
+ public:
+  struct Options {
+    Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
+    Options(MessageLoop::Type type, size_t size)
+        : message_loop_type(type), stack_size(size) {}
+
+    // Specifies the type of message loop that will be allocated on the thread.
+    MessageLoop::Type message_loop_type;
+
+    // Specifies the maximum stack size that the thread is allowed to use.
+    // This does not necessarily correspond to the thread's initial stack size.
+    // A value of 0 indicates that the default maximum should be used.
+    size_t stack_size;
+  };
+
+  // Constructor.
+  // name is a display string to identify the thread.
+  explicit Thread(const char* name);
+
+  // Destroys the thread, stopping it if necessary.
+  //
+  // NOTE: If you are subclassing from Thread, and you wish for your CleanUp
+  // method to be called, then you need to call Stop() from your destructor.
+  //
+  virtual ~Thread();
+
+  // Starts the thread.  Returns true if the thread was successfully started;
+  // otherwise, returns false.  Upon successful return, the message_loop()
+  // getter will return non-null.
+  //
+  // Note: This function can't be called on Windows with the loader lock held;
+  // i.e. during a DllMain, global object construction or destruction, atexit()
+  // callback.
+  bool Start();
+
+  // Starts the thread. Behaves exactly like Start in addition to allow to
+  // override the default options.
+  //
+  // Note: This function can't be called on Windows with the loader lock held;
+  // i.e. during a DllMain, global object construction or destruction, atexit()
+  // callback.
+  bool StartWithOptions(const Options& options);
+
+  // Signals the thread to exit and returns once the thread has exited.  After
+  // this method returns, the Thread object is completely reset and may be used
+  // as if it were newly constructed (i.e., Start may be called again).
+  //
+  // Stop may be called multiple times and is simply ignored if the thread is
+  // already stopped.
+  //
+  // NOTE: This method is optional.  It is not strictly necessary to call this
+  // method as the Thread's destructor will take care of stopping the thread if
+  // necessary.
+  //
+  void Stop();
+
+  // Signals the thread to exit in the near future.
+  //
+  // WARNING: This function is not meant to be commonly used. Use at your own
+  // risk. Calling this function will cause message_loop() to become invalid in
+  // the near future. This function was created to workaround a specific
+  // deadlock on Windows with printer worker thread. In any other case, Stop()
+  // should be used.
+  //
+  // StopSoon should not be called multiple times as it is risky to do so. It
+  // could cause a timing issue in message_loop() access. Call Stop() to reset
+  // the thread object once it is known that the thread has quit.
+  void StopSoon();
+
+  // Returns the message loop for this thread.  Use the MessageLoop's
+  // PostTask methods to execute code on the thread.  This only returns
+  // non-null after a successful call to Start.  After Stop has been called,
+  // this will return NULL.
+  //
+  // NOTE: You must not call this MessageLoop's Quit method directly.  Use
+  // the Thread's Stop method instead.
+  //
+  MessageLoop* message_loop() const { return message_loop_; }
+
+  // Returns a MessageLoopProxy for this thread.  Use the MessageLoopProxy's
+  // PostTask methods to execute code on the thread.  This only returns
+  // non-NULL after a successful call to Start. After Stop has been called,
+  // this will return NULL. Callers can hold on to this even after the thread
+  // is gone.
+  // TODO(sanjeevr): Look into merging MessageLoop and MessageLoopProxy.
+  scoped_refptr<MessageLoopProxy> message_loop_proxy() const {
+    return message_loop_->message_loop_proxy();
+  }
+
+  // Set the name of this thread (for display in debugger too).
+  const std::string &thread_name() { return name_; }
+
+  // The native thread handle.
+  PlatformThreadHandle thread_handle() { return thread_; }
+
+  // The thread ID.
+  PlatformThreadId thread_id() const { return thread_id_; }
+
+  // Returns true if the thread has been started, and not yet stopped.
+  // When a thread is running, |thread_id_| is a valid id.
+  bool IsRunning() const { return thread_id_ != kInvalidThreadId; }
+
+ protected:
+  // Called just prior to starting the message loop
+  virtual void Init() {}
+
+  // Called to start the message loop
+  virtual void Run(MessageLoop* message_loop);
+
+  // Called just after the message loop ends
+  virtual void CleanUp() {}
+
+  // Called after the message loop has been deleted. In general clients
+  // should prefer to use CleanUp(). This method is used when code needs to
+  // be run after all of the MessageLoop::DestructionObservers have completed.
+  virtual void CleanUpAfterMessageLoopDestruction() {}
+
+  static void SetThreadWasQuitProperly(bool flag);
+  static bool GetThreadWasQuitProperly();
+
+  void set_message_loop(MessageLoop* message_loop) {
+    message_loop_ = message_loop;
+  }
+
+ private:
+  bool thread_was_started() const { return started_; }
+
+  // PlatformThread::Delegate methods:
+  virtual void ThreadMain();
+
+  // Whether we successfully started the thread.
+  bool started_;
+
+  // If true, we're in the middle of stopping, and shouldn't access
+  // |message_loop_|. It may non-NULL and invalid.
+  bool stopping_;
+
+  // Used to pass data to ThreadMain.
+  struct StartupData;
+  StartupData* startup_data_;
+
+  // The thread's handle.
+  PlatformThreadHandle thread_;
+
+  // The thread's message loop.  Valid only while the thread is alive.  Set
+  // by the created thread.
+  MessageLoop* message_loop_;
+
+  // Our thread's ID.
+  PlatformThreadId thread_id_;
+
+  // The name of the thread.  Used for debugging purposes.
+  std::string name_;
+
+  friend class ThreadQuitTask;
+
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREAD_H_
diff --git a/base/threading/thread_collision_warner.cc b/base/threading/thread_collision_warner.cc
new file mode 100644 (file)
index 0000000..547e11c
--- /dev/null
@@ -0,0 +1,64 @@
+// 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/threading/thread_collision_warner.h"
+
+#include "base/logging.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+void DCheckAsserter::warn() {
+  NOTREACHED() << "Thread Collision";
+}
+
+static subtle::Atomic32 CurrentThread() {
+  const PlatformThreadId current_thread_id = PlatformThread::CurrentId();
+  // We need to get the thread id into an atomic data type. This might be a
+  // truncating conversion, but any loss-of-information just increases the
+  // chance of a fault negative, not a false positive.
+  const subtle::Atomic32 atomic_thread_id =
+      static_cast<subtle::Atomic32>(current_thread_id);
+
+  return atomic_thread_id;
+}
+
+void ThreadCollisionWarner::EnterSelf() {
+  // If the active thread is 0 then I'll write the current thread ID
+  // if two or more threads arrive here only one will succeed to
+  // write on valid_thread_id_ the current thread ID.
+  subtle::Atomic32 current_thread_id = CurrentThread();
+
+  int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
+                                                        0,
+                                                        current_thread_id);
+  if (previous_value != 0 && previous_value != current_thread_id) {
+    // gotcha! a thread is trying to use the same class and that is
+    // not current thread.
+    asserter_->warn();
+  }
+
+  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+}
+
+void ThreadCollisionWarner::Enter() {
+  subtle::Atomic32 current_thread_id = CurrentThread();
+
+  if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
+                                       0,
+                                       current_thread_id) != 0) {
+    // gotcha! another thread is trying to use the same class.
+    asserter_->warn();
+  }
+
+  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+}
+
+void ThreadCollisionWarner::Leave() {
+  if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) {
+    subtle::NoBarrier_Store(&valid_thread_id_, 0);
+  }
+}
+
+}  // namespace base
diff --git a/base/threading/thread_collision_warner.h b/base/threading/thread_collision_warner.h
new file mode 100644 (file)
index 0000000..4460602
--- /dev/null
@@ -0,0 +1,244 @@
+// 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_COLLISION_WARNER_H_
+#define BASE_THREADING_THREAD_COLLISION_WARNER_H_
+#pragma once
+
+#include <memory>
+
+#include "base/base_export.h"
+#include "base/atomicops.h"
+
+// A helper class alongside macros to be used to verify assumptions about thread
+// safety of a class.
+//
+// Example: Queue implementation non thread-safe but still usable if clients
+//          are synchronized somehow.
+//
+//          In this case the macro DFAKE_SCOPED_LOCK has to be
+//          used, it checks that if a thread is inside the push/pop then
+//          noone else is still inside the pop/push
+//
+// class NonThreadSafeQueue {
+//  public:
+//   ...
+//   void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... }
+//   int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Queue implementation non thread-safe but still usable if clients
+//          are synchronized somehow, it calls a method to "protect" from
+//          a "protected" method
+//
+//          In this case the macro DFAKE_SCOPED_RECURSIVE_LOCK
+//          has to be used, it checks that if a thread is inside the push/pop
+//          then noone else is still inside the pop/push
+//
+// class NonThreadSafeQueue {
+//  public:
+//   void push(int) {
+//     DFAKE_SCOPED_LOCK(push_pop_);
+//     ...
+//   }
+//   int pop() {
+//     DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
+//     bar();
+//     ...
+//   }
+//   void bar() { DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Queue implementation not usable even if clients are synchronized,
+//          so only one thread in the class life cycle can use the two members
+//          push/pop.
+//
+//          In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the
+//          specified
+//          critical section the first time a thread enters push or pop, from
+//          that time on only that thread is allowed to execute push or pop.
+//
+// class NonThreadSafeQueue {
+//  public:
+//   ...
+//   void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
+//   int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Class that has to be contructed/destroyed on same thread, it has
+//          a "shareable" method (with external syncronization) and a not
+//          shareable method (even with external synchronization).
+//
+//          In this case 3 Critical sections have to be defined
+//
+// class ExoticClass {
+//  public:
+//   ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//   ~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//
+//   void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... }
+//   void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(ctor_dtor_);
+//   DFAKE_MUTEX(shareable_section_);
+// };
+
+
+#if !defined(NDEBUG)
+
+// Defines a class member that acts like a mutex. It is used only as a
+// verification tool.
+#define DFAKE_MUTEX(obj) \
+     mutable base::ThreadCollisionWarner obj
+// Asserts the call is never called simultaneously in two threads. Used at
+// member function scope.
+#define DFAKE_SCOPED_LOCK(obj) \
+     base::ThreadCollisionWarner::ScopedCheck s_check_##obj(&obj)
+// Asserts the call is never called simultaneously in two threads. Used at
+// member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks.
+#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \
+     base::ThreadCollisionWarner::ScopedRecursiveCheck sr_check_##obj(&obj)
+// Asserts the code is always executed in the same thread.
+#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \
+     base::ThreadCollisionWarner::Check check_##obj(&obj)
+
+#else
+
+#define DFAKE_MUTEX(obj)
+#define DFAKE_SCOPED_LOCK(obj) ((void)0)
+#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) ((void)0)
+#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ((void)0)
+
+#endif
+
+namespace base {
+
+// The class ThreadCollisionWarner uses an Asserter to notify the collision
+// 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 BASE_EXPORT AsserterBase {
+  virtual ~AsserterBase() {}
+  virtual void warn() = 0;
+};
+
+struct BASE_EXPORT DCheckAsserter : public AsserterBase {
+  virtual ~DCheckAsserter() {}
+  virtual void warn();
+};
+
+class BASE_EXPORT ThreadCollisionWarner {
+ public:
+  // The parameter asserter is there only for test purpose
+  ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter())
+      : valid_thread_id_(0),
+        counter_(0),
+        asserter_(asserter) {}
+
+  ~ThreadCollisionWarner() {
+    delete asserter_;
+  }
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_LOCK_THREAD_LOCKED
+  // 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 BASE_EXPORT Check {
+   public:
+    explicit Check(ThreadCollisionWarner* warner)
+        : warner_(warner) {
+      warner_->EnterSelf();
+    }
+
+    ~Check() {}
+
+   private:
+    ThreadCollisionWarner* warner_;
+
+    DISALLOW_COPY_AND_ASSIGN(Check);
+  };
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_LOCK
+  class BASE_EXPORT ScopedCheck {
+   public:
+    explicit ScopedCheck(ThreadCollisionWarner* warner)
+        : warner_(warner) {
+      warner_->Enter();
+    }
+
+    ~ScopedCheck() {
+      warner_->Leave();
+    }
+
+   private:
+    ThreadCollisionWarner* warner_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
+  };
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_RECURSIVE_LOCK
+  class BASE_EXPORT ScopedRecursiveCheck {
+   public:
+    explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner)
+        : warner_(warner) {
+      warner_->EnterSelf();
+    }
+
+    ~ScopedRecursiveCheck() {
+      warner_->Leave();
+    }
+
+   private:
+    ThreadCollisionWarner* warner_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedRecursiveCheck);
+  };
+
+ private:
+  // This method stores the current thread identifier and does a DCHECK
+  // if a another thread has already done it, it is safe if same thread
+  // calls this multiple time (recursion allowed).
+  void EnterSelf();
+
+  // Same as EnterSelf but recursion is not allowed.
+  void Enter();
+
+  // Removes the thread_id stored in order to allow other threads to
+  // call EnterSelf or Enter.
+  void Leave();
+
+  // This stores the thread id that is inside the critical section, if the
+  // value is 0 then no thread is inside.
+  volatile subtle::Atomic32 valid_thread_id_;
+
+  // Counter to trace how many time a critical section was "pinned"
+  // (when allowed) in order to unpin it when counter_ reaches 0.
+  volatile subtle::Atomic32 counter_;
+
+  // Here only for class unit tests purpose, during the test I need to not
+  // DCHECK but notify the collision with something else.
+  AsserterBase* asserter_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadCollisionWarner);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_COLLISION_WARNER_H_
diff --git a/base/time.h b/base/time.h
new file mode 100644 (file)
index 0000000..aa97f0a
--- /dev/null
@@ -0,0 +1,566 @@
+// 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.
+
+// Time represents an absolute point in time, internally represented as
+// microseconds (s/1,000,000) since a platform-dependent epoch.  Each
+// platform's epoch, along with other system-dependent clock interface
+// routines, is defined in time_PLATFORM.cc.
+//
+// TimeDelta represents a duration of time, internally represented in
+// microseconds.
+//
+// TimeTicks represents an abstract time that is always incrementing for use
+// in measuring time durations. It is internally represented in microseconds.
+// It can not be converted to a human-readable time, but is guaranteed not to
+// decrease (if the user changes the computer clock, Time::Now() may actually
+// decrease or jump).
+//
+// These classes are represented as only a 64-bit value, so they can be
+// efficiently passed by value.
+
+#ifndef BASE_TIME_H_
+#define BASE_TIME_H_
+#pragma once
+
+#include <time.h>
+
+#include "base/atomicops.h"
+#include "base/base_export.h"
+#include "base/basictypes.h"
+
+#if defined(OS_POSIX)
+// For struct timeval.
+#include <sys/time.h>
+#endif
+
+#if defined(OS_WIN)
+// For FILETIME in FromFileTime, until it moves to a new converter class.
+// See TODO(iyengar) below.
+#include <windows.h>
+#endif
+
+namespace base {
+
+class Time;
+class TimeTicks;
+
+// TimeDelta ------------------------------------------------------------------
+
+class BASE_EXPORT TimeDelta {
+ public:
+  TimeDelta() : delta_(0) {
+  }
+
+  // Converts units of time to TimeDeltas.
+  static TimeDelta FromDays(int64 days);
+  static TimeDelta FromHours(int64 hours);
+  static TimeDelta FromMinutes(int64 minutes);
+  static TimeDelta FromSeconds(int64 secs);
+  static TimeDelta FromMilliseconds(int64 ms);
+  static TimeDelta FromMicroseconds(int64 us);
+
+  // Returns the internal numeric value of the TimeDelta object. Please don't
+  // use this and do arithmetic on it, as it is more error prone than using the
+  // provided operators.
+  int64 ToInternalValue() const {
+    return delta_;
+  }
+
+#if defined(OS_POSIX)
+  struct timespec ToTimeSpec() const;
+#endif
+
+  // Returns the time delta in some unit. The F versions return a floating
+  // point value, the "regular" versions return a rounded-down value.
+  //
+  // InMillisecondsRoundedUp() instead returns an integer that is rounded up
+  // to the next full millisecond.
+  int InDays() const;
+  int InHours() const;
+  int InMinutes() const;
+  double InSecondsF() const;
+  int64 InSeconds() const;
+  double InMillisecondsF() const;
+  int64 InMilliseconds() const;
+  int64 InMillisecondsRoundedUp() const;
+  int64 InMicroseconds() const;
+
+  TimeDelta& operator=(TimeDelta other) {
+    delta_ = other.delta_;
+    return *this;
+  }
+
+  // Computations with other deltas.
+  TimeDelta operator+(TimeDelta other) const {
+    return TimeDelta(delta_ + other.delta_);
+  }
+  TimeDelta operator-(TimeDelta other) const {
+    return TimeDelta(delta_ - other.delta_);
+  }
+
+  TimeDelta& operator+=(TimeDelta other) {
+    delta_ += other.delta_;
+    return *this;
+  }
+  TimeDelta& operator-=(TimeDelta other) {
+    delta_ -= other.delta_;
+    return *this;
+  }
+  TimeDelta operator-() const {
+    return TimeDelta(-delta_);
+  }
+
+  // Computations with ints, note that we only allow multiplicative operations
+  // with ints, and additive operations with other deltas.
+  TimeDelta operator*(int64 a) const {
+    return TimeDelta(delta_ * a);
+  }
+  TimeDelta operator/(int64 a) const {
+    return TimeDelta(delta_ / a);
+  }
+  TimeDelta& operator*=(int64 a) {
+    delta_ *= a;
+    return *this;
+  }
+  TimeDelta& operator/=(int64 a) {
+    delta_ /= a;
+    return *this;
+  }
+  int64 operator/(TimeDelta a) const {
+    return delta_ / a.delta_;
+  }
+
+  // Defined below because it depends on the definition of the other classes.
+  Time operator+(Time t) const;
+  TimeTicks operator+(TimeTicks t) const;
+
+  // Comparison operators.
+  bool operator==(TimeDelta other) const {
+    return delta_ == other.delta_;
+  }
+  bool operator!=(TimeDelta other) const {
+    return delta_ != other.delta_;
+  }
+  bool operator<(TimeDelta other) const {
+    return delta_ < other.delta_;
+  }
+  bool operator<=(TimeDelta other) const {
+    return delta_ <= other.delta_;
+  }
+  bool operator>(TimeDelta other) const {
+    return delta_ > other.delta_;
+  }
+  bool operator>=(TimeDelta other) const {
+    return delta_ >= other.delta_;
+  }
+
+ private:
+  friend class Time;
+  friend class TimeTicks;
+  friend TimeDelta operator*(int64 a, TimeDelta td);
+
+  // Constructs a delta given the duration in microseconds. This is private
+  // to avoid confusion by callers with an integer constructor. Use
+  // FromSeconds, FromMilliseconds, etc. instead.
+  explicit TimeDelta(int64 delta_us) : delta_(delta_us) {
+  }
+
+  // Delta in microseconds.
+  int64 delta_;
+};
+
+inline TimeDelta operator*(int64 a, TimeDelta td) {
+  return TimeDelta(a * td.delta_);
+}
+
+// Time -----------------------------------------------------------------------
+
+// Represents a wall clock time.
+class BASE_EXPORT Time {
+ public:
+  static const int64 kMillisecondsPerSecond = 1000;
+  static const int64 kMicrosecondsPerMillisecond = 1000;
+  static const int64 kMicrosecondsPerSecond = kMicrosecondsPerMillisecond *
+                                              kMillisecondsPerSecond;
+  static const int64 kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
+  static const int64 kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
+  static const int64 kMicrosecondsPerDay = kMicrosecondsPerHour * 24;
+  static const int64 kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
+  static const int64 kNanosecondsPerMicrosecond = 1000;
+  static const int64 kNanosecondsPerSecond = kNanosecondsPerMicrosecond *
+                                             kMicrosecondsPerSecond;
+
+#if !defined(OS_WIN)
+  // On Mac & Linux, this value is the delta from the Windows epoch of 1601 to
+  // the Posix delta of 1970. This is used for migrating between the old
+  // 1970-based epochs to the new 1601-based ones. It should be removed from
+  // this global header and put in the platform-specific ones when we remove the
+  // migration code.
+  static const int64 kWindowsEpochDeltaMicroseconds;
+#endif
+
+  // 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 BASE_EXPORT 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.)
+    int day_of_month;  // 1-based day of month (1-31)
+    int hour;          // Hour within the current day (0-23)
+    int minute;        // Minute within the current hour (0-59)
+    int second;        // Second within the current minute (0-59 plus leap
+                       //   seconds which may take it up to 60).
+    int millisecond;   // Milliseconds within the current second (0-999)
+
+    // A cursory test for whether the data members are within their
+    // respective ranges. A 'true' return value does not guarantee the
+    // Exploded value can be successfully converted to a Time value.
+    bool HasValidValues() const;
+  };
+
+  // Contains the NULL time. Use Time::Now() to get the current time.
+  explicit Time() : us_(0) {
+  }
+
+  // Returns true if the time object has not been initialized.
+  bool is_null() const {
+    return us_ == 0;
+  }
+
+  // Returns the time for epoch in Unix-like system (Jan 1, 1970).
+  static Time UnixEpoch();
+
+  // Returns the current time. Watch out, the system might adjust its clock
+  // in which case time will actually go backwards. We don't guarantee that
+  // times are increasing, or that two calls to Now() won't be the same.
+  static Time Now();
+
+  // Returns the current time. Same as Now() except that this function always
+  // uses system time so that there are no discrepancies between the returned
+  // time and system time even on virtual environments including our test bot.
+  // For timing sensitive unittests, this function should be used.
+  static Time NowFromSystemTime();
+
+  // Converts to/from time_t in UTC and a Time class.
+  // TODO(brettw) this should be removed once everybody starts using the |Time|
+  // class.
+  static Time FromTimeT(time_t tt);
+  time_t ToTimeT() const;
+
+  // Converts time to/from a double which is the number of seconds since epoch
+  // (Jan 1, 1970).  Webkit uses this format to represent time.
+  // Because WebKit initializes double time value to 0 to indicate "not
+  // initialized", we map it to empty Time object that also means "not
+  // initialized".
+  static Time FromDoubleT(double dt);
+  double ToDoubleT() const;
+
+#if defined(OS_POSIX)
+  struct timeval ToTimeVal() const;
+#endif
+
+#if defined(OS_WIN)
+  static Time FromFileTime(FILETIME ft);
+  FILETIME ToFileTime() const;
+
+  // The minimum time of a low resolution timer.  This is basically a windows
+  // constant of ~15.6ms.  While it does vary on some older OS versions, we'll
+  // treat it as static across all windows versions.
+  static const int kMinLowResolutionThresholdMs = 16;
+
+  // Enable or disable Windows high resolution timer. If the high resolution
+  // timer is not enabled, calls to ActivateHighResolutionTimer will fail.
+  // When disabling the high resolution timer, this function will not cause
+  // the high resolution timer to be deactivated, but will prevent future
+  // activations.
+  // Must be called from the main thread.
+  // For more details see comments in time_win.cc.
+  static void EnableHighResolutionTimer(bool enable);
+
+  // Activates or deactivates the high resolution timer based on the |activate|
+  // flag.  If the HighResolutionTimer is not Enabled (see
+  // EnableHighResolutionTimer), this function will return false.  Otherwise
+  // returns true.  Each successful activate call must be paired with a
+  // subsequent deactivate call.
+  // All callers to activate the high resolution timer must eventually call
+  // this function to deactivate the high resolution timer.
+  static bool ActivateHighResolutionTimer(bool activate);
+
+  // Returns true if the high resolution timer is both enabled and activated.
+  // This is provided for testing only, and is not tracked in a thread-safe
+  // way.
+  static bool IsHighResolutionTimerInUse();
+#endif
+
+  // Converts an exploded structure representing either the local time or UTC
+  // into a Time class.
+  static Time FromUTCExploded(const Exploded& exploded) {
+    return FromExploded(false, exploded);
+  }
+  static Time FromLocalExploded(const Exploded& exploded) {
+    return FromExploded(true, exploded);
+  }
+
+  // Converts an integer value representing Time to a class. This is used
+  // when deserializing a |Time| structure, using a value known to be
+  // compatible. It is not provided as a constructor because the integer type
+  // may be unclear from the perspective of a caller.
+  static Time FromInternalValue(int64 us) {
+    return Time(us);
+  }
+
+  // Converts a string representation of time to a Time object.
+  // An example of a time string which is converted is as below:-
+  // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified
+  // in the input string, we assume local time.
+  // TODO(iyengar) Move the FromString/FromTimeT/ToTimeT/FromFileTime to
+  // a new time converter class.
+  static bool FromString(const char* time_string, Time* parsed_time);
+
+  // For serializing, use FromInternalValue to reconstitute. Please don't use
+  // this and do arithmetic on it, as it is more error prone than using the
+  // provided operators.
+  int64 ToInternalValue() const {
+    return us_;
+  }
+
+  // Fills the given exploded structure with either the local time or UTC from
+  // this time structure (containing UTC).
+  void UTCExplode(Exploded* exploded) const {
+    return Explode(false, exploded);
+  }
+  void LocalExplode(Exploded* exploded) const {
+    return Explode(true, exploded);
+  }
+
+  // Rounds this time down to the nearest day in local time. It will represent
+  // midnight on that day.
+  Time LocalMidnight() const;
+
+  Time& operator=(Time other) {
+    us_ = other.us_;
+    return *this;
+  }
+
+  // Compute the difference between two times.
+  TimeDelta operator-(Time other) const {
+    return TimeDelta(us_ - other.us_);
+  }
+
+  // Modify by some time delta.
+  Time& operator+=(TimeDelta delta) {
+    us_ += delta.delta_;
+    return *this;
+  }
+  Time& operator-=(TimeDelta delta) {
+    us_ -= delta.delta_;
+    return *this;
+  }
+
+  // Return a new time modified by some delta.
+  Time operator+(TimeDelta delta) const {
+    return Time(us_ + delta.delta_);
+  }
+  Time operator-(TimeDelta delta) const {
+    return Time(us_ - delta.delta_);
+  }
+
+  // Comparison operators
+  bool operator==(Time other) const {
+    return us_ == other.us_;
+  }
+  bool operator!=(Time other) const {
+    return us_ != other.us_;
+  }
+  bool operator<(Time other) const {
+    return us_ < other.us_;
+  }
+  bool operator<=(Time other) const {
+    return us_ <= other.us_;
+  }
+  bool operator>(Time other) const {
+    return us_ > other.us_;
+  }
+  bool operator>=(Time other) const {
+    return us_ >= other.us_;
+  }
+
+ private:
+  friend class TimeDelta;
+
+  explicit Time(int64 us) : us_(us) {
+  }
+
+  // Explodes the given time to either local time |is_local = true| or UTC
+  // |is_local = false|.
+  void Explode(bool is_local, Exploded* exploded) const;
+
+  // Unexplodes a given time assuming the source is either local time
+  // |is_local = true| or UTC |is_local = false|.
+  static Time FromExploded(bool is_local, const Exploded& exploded);
+
+  // The representation of Jan 1, 1970 UTC in microseconds since the
+  // platform-dependent epoch.
+  static const int64 kTimeTToMicrosecondsOffset;
+
+#if defined(OS_WIN)
+  // Indicates whether fast timers are usable right now.  For instance,
+  // when using battery power, we might elect to prevent high speed timers
+  // which would draw more power.
+  static bool high_resolution_timer_enabled_;
+  // Count of activations on the high resolution timer.  Only use in tests
+  // which are single threaded.
+  static int high_resolution_timer_activated_;
+#endif
+
+  // Time in microseconds in UTC.
+  int64 us_;
+};
+
+// Inline the TimeDelta factory methods, for fast TimeDelta construction.
+
+// static
+inline TimeDelta TimeDelta::FromDays(int64 days) {
+  return TimeDelta(days * Time::kMicrosecondsPerDay);
+}
+
+// static
+inline TimeDelta TimeDelta::FromHours(int64 hours) {
+  return TimeDelta(hours * Time::kMicrosecondsPerHour);
+}
+
+// static
+inline TimeDelta TimeDelta::FromMinutes(int64 minutes) {
+  return TimeDelta(minutes * Time::kMicrosecondsPerMinute);
+}
+
+// static
+inline TimeDelta TimeDelta::FromSeconds(int64 secs) {
+  return TimeDelta(secs * Time::kMicrosecondsPerSecond);
+}
+
+// static
+inline TimeDelta TimeDelta::FromMilliseconds(int64 ms) {
+  return TimeDelta(ms * Time::kMicrosecondsPerMillisecond);
+}
+
+// static
+inline TimeDelta TimeDelta::FromMicroseconds(int64 us) {
+  return TimeDelta(us);
+}
+
+inline Time TimeDelta::operator+(Time t) const {
+  return Time(t.us_ + delta_);
+}
+
+// TimeTicks ------------------------------------------------------------------
+
+class BASE_EXPORT TimeTicks {
+ public:
+  TimeTicks() : ticks_(0) {
+  }
+
+  // Platform-dependent tick count representing "right now."
+  // The resolution of this clock is ~1-15ms.  Resolution varies depending
+  // on hardware/operating system configuration.
+  static TimeTicks Now();
+
+  // Returns a platform-dependent high-resolution tick count. Implementation
+  // is hardware dependent and may or may not return sub-millisecond
+  // resolution.  THIS CALL IS GENERALLY MUCH MORE EXPENSIVE THAN Now() AND
+  // SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED.
+  static TimeTicks HighResNow();
+
+#if defined(OS_WIN)
+  // Get the absolute value of QPC time drift. For testing.
+  static int64 GetQPCDriftMicroseconds();
+
+  // Returns true if the high resolution clock is working on this system.
+  // This is only for testing.
+  static bool IsHighResClockWorking();
+#endif
+
+  // Returns true if this object has not been initialized.
+  bool is_null() const {
+    return ticks_ == 0;
+  }
+
+  // Returns the internal numeric value of the TimeTicks object.
+  int64 ToInternalValue() const {
+    return ticks_;
+  }
+
+  TimeTicks& operator=(TimeTicks other) {
+    ticks_ = other.ticks_;
+    return *this;
+  }
+
+  // Compute the difference between two times.
+  TimeDelta operator-(TimeTicks other) const {
+    return TimeDelta(ticks_ - other.ticks_);
+  }
+
+  // Modify by some time delta.
+  TimeTicks& operator+=(TimeDelta delta) {
+    ticks_ += delta.delta_;
+    return *this;
+  }
+  TimeTicks& operator-=(TimeDelta delta) {
+    ticks_ -= delta.delta_;
+    return *this;
+  }
+
+  // Return a new TimeTicks modified by some delta.
+  TimeTicks operator+(TimeDelta delta) const {
+    return TimeTicks(ticks_ + delta.delta_);
+  }
+  TimeTicks operator-(TimeDelta delta) const {
+    return TimeTicks(ticks_ - delta.delta_);
+  }
+
+  // Comparison operators
+  bool operator==(TimeTicks other) const {
+    return ticks_ == other.ticks_;
+  }
+  bool operator!=(TimeTicks other) const {
+    return ticks_ != other.ticks_;
+  }
+  bool operator<(TimeTicks other) const {
+    return ticks_ < other.ticks_;
+  }
+  bool operator<=(TimeTicks other) const {
+    return ticks_ <= other.ticks_;
+  }
+  bool operator>(TimeTicks other) const {
+    return ticks_ > other.ticks_;
+  }
+  bool operator>=(TimeTicks other) const {
+    return ticks_ >= other.ticks_;
+  }
+
+ protected:
+  friend class TimeDelta;
+
+  // Please use Now() to create a new object. This is for internal use
+  // and testing. Ticks is in microseconds.
+  explicit TimeTicks(int64 ticks) : ticks_(ticks) {
+  }
+
+  // Tick count in microseconds.
+  int64 ticks_;
+
+#if defined(OS_WIN)
+  typedef DWORD (*TickFunctionType)(void);
+  static TickFunctionType SetMockTickFunction(TickFunctionType ticker);
+#endif
+};
+
+inline TimeTicks TimeDelta::operator+(TimeTicks t) const {
+  return TimeTicks(t.ticks_ + delta_);
+}
+
+}  // namespace base
+
+#endif  // BASE_TIME_H_
diff --git a/base/tuple.h b/base/tuple.h
new file mode 100644 (file)
index 0000000..65d0908
--- /dev/null
@@ -0,0 +1,1056 @@
+// 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.
+
+// A Tuple is a generic templatized container, similar in concept to std::pair.
+// There are classes Tuple0 to Tuple6, cooresponding to the number of elements
+// it contains.  The convenient MakeTuple() function takes 0 to 6 arguments,
+// and will construct and return the appropriate Tuple object.  The functions
+// DispatchToMethod and DispatchToFunction take a function pointer or instance
+// and method pointer, and unpack a tuple into arguments to the call.
+//
+// Tuple elements are copied by value, and stored in the tuple.  See the unit
+// tests for more details of how/when the values are copied.
+//
+// Example usage:
+//   // These two methods of creating a Tuple are identical.
+//   Tuple2<int, const char*> tuple_a(1, "wee");
+//   Tuple2<int, const char*> tuple_b = MakeTuple(1, "wee");
+//
+//   void SomeFunc(int a, const char* b) { }
+//   DispatchToFunction(&SomeFunc, tuple_a);  // SomeFunc(1, "wee")
+//   DispatchToFunction(
+//       &SomeFunc, MakeTuple(10, "foo"));    // SomeFunc(10, "foo")
+//
+//   struct { void SomeMeth(int a, int b, int c) { } } foo;
+//   DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3));
+//   // foo->SomeMeth(1, 2, 3);
+
+#ifndef BASE_TUPLE_H__
+#define BASE_TUPLE_H__
+#pragma once
+
+#if defined(OS_CHROMEOS)
+// To troubleshoot crosbug.com/7327.
+#include "base/logging.h"
+#endif
+// Traits ----------------------------------------------------------------------
+//
+// A simple traits class for tuple arguments.
+//
+// ValueType: the bare, nonref version of a type (same as the type for nonrefs).
+// RefType: the ref version of a type (same as the type for refs).
+// ParamType: what type to pass to functions (refs should not be constified).
+
+template <class P>
+struct TupleTraits {
+  typedef P ValueType;
+  typedef P& RefType;
+  typedef const P& ParamType;
+};
+
+template <class P>
+struct TupleTraits<P&> {
+  typedef P ValueType;
+  typedef P& RefType;
+  typedef P& ParamType;
+};
+
+template <class P>
+struct TupleTypes { };
+
+// Tuple -----------------------------------------------------------------------
+//
+// This set of classes is useful for bundling 0 or more heterogeneous data types
+// into a single variable.  The advantage of this is that it greatly simplifies
+// function objects that need to take an arbitrary number of parameters; see
+// RunnableMethod and IPC::MessageWithTuple.
+//
+// Tuple0 is supplied to act as a 'void' type.  It can be used, for example,
+// when dispatching to a function that accepts no arguments (see the
+// Dispatchers below).
+// Tuple1<A> is rarely useful.  One such use is when A is non-const ref that you
+// want filled by the dispatchee, and the tuple is merely a container for that
+// output (a "tier").  See MakeRefTuple and its usages.
+
+struct Tuple0 {
+  typedef Tuple0 ValueTuple;
+  typedef Tuple0 RefTuple;
+  typedef Tuple0 ParamTuple;
+};
+
+template <class A>
+struct Tuple1 {
+ public:
+  typedef A TypeA;
+
+  Tuple1() {}
+  explicit Tuple1(typename TupleTraits<A>::ParamType a) : a(a) {}
+
+  A a;
+};
+
+template <class A, class B>
+struct Tuple2 {
+ public:
+  typedef A TypeA;
+  typedef B TypeB;
+
+  Tuple2() {}
+  Tuple2(typename TupleTraits<A>::ParamType a,
+         typename TupleTraits<B>::ParamType b)
+      : a(a), b(b) {
+  }
+
+  A a;
+  B b;
+};
+
+template <class A, class B, class C>
+struct Tuple3 {
+ public:
+  typedef A TypeA;
+  typedef B TypeB;
+  typedef C TypeC;
+
+  Tuple3() {}
+  Tuple3(typename TupleTraits<A>::ParamType a,
+         typename TupleTraits<B>::ParamType b,
+         typename TupleTraits<C>::ParamType c)
+      : a(a), b(b), c(c){
+  }
+
+  A a;
+  B b;
+  C c;
+};
+
+template <class A, class B, class C, class D>
+struct Tuple4 {
+ public:
+  typedef A TypeA;
+  typedef B TypeB;
+  typedef C TypeC;
+  typedef D TypeD;
+
+  Tuple4() {}
+  Tuple4(typename TupleTraits<A>::ParamType a,
+         typename TupleTraits<B>::ParamType b,
+         typename TupleTraits<C>::ParamType c,
+         typename TupleTraits<D>::ParamType d)
+      : a(a), b(b), c(c), d(d) {
+  }
+
+  A a;
+  B b;
+  C c;
+  D d;
+};
+
+template <class A, class B, class C, class D, class E>
+struct Tuple5 {
+ public:
+  typedef A TypeA;
+  typedef B TypeB;
+  typedef C TypeC;
+  typedef D TypeD;
+  typedef E TypeE;
+
+  Tuple5() {}
+  Tuple5(typename TupleTraits<A>::ParamType a,
+    typename TupleTraits<B>::ParamType b,
+    typename TupleTraits<C>::ParamType c,
+    typename TupleTraits<D>::ParamType d,
+    typename TupleTraits<E>::ParamType e)
+    : a(a), b(b), c(c), d(d), e(e) {
+  }
+
+  A a;
+  B b;
+  C c;
+  D d;
+  E e;
+};
+
+template <class A, class B, class C, class D, class E, class F>
+struct Tuple6 {
+ public:
+  typedef A TypeA;
+  typedef B TypeB;
+  typedef C TypeC;
+  typedef D TypeD;
+  typedef E TypeE;
+  typedef F TypeF;
+
+  Tuple6() {}
+  Tuple6(typename TupleTraits<A>::ParamType a,
+    typename TupleTraits<B>::ParamType b,
+    typename TupleTraits<C>::ParamType c,
+    typename TupleTraits<D>::ParamType d,
+    typename TupleTraits<E>::ParamType e,
+    typename TupleTraits<F>::ParamType f)
+    : a(a), b(b), c(c), d(d), e(e), f(f) {
+  }
+
+  A a;
+  B b;
+  C c;
+  D d;
+  E e;
+  F f;
+};
+
+template <class A, class B, class C, class D, class E, class F, class G>
+struct Tuple7 {
+ public:
+  typedef A TypeA;
+  typedef B TypeB;
+  typedef C TypeC;
+  typedef D TypeD;
+  typedef E TypeE;
+  typedef F TypeF;
+  typedef G TypeG;
+
+  Tuple7() {}
+  Tuple7(typename TupleTraits<A>::ParamType a,
+    typename TupleTraits<B>::ParamType b,
+    typename TupleTraits<C>::ParamType c,
+    typename TupleTraits<D>::ParamType d,
+    typename TupleTraits<E>::ParamType e,
+    typename TupleTraits<F>::ParamType f,
+    typename TupleTraits<G>::ParamType g)
+    : a(a), b(b), c(c), d(d), e(e), f(f), g(g) {
+  }
+
+  A a;
+  B b;
+  C c;
+  D d;
+  E e;
+  F f;
+  G g;
+};
+
+template <class A, class B, class C, class D, class E, class F, class G,
+          class H>
+struct Tuple8 {
+ public:
+  typedef A TypeA;
+  typedef B TypeB;
+  typedef C TypeC;
+  typedef D TypeD;
+  typedef E TypeE;
+  typedef F TypeF;
+  typedef G TypeG;
+  typedef H TypeH;
+
+  Tuple8() {}
+  Tuple8(typename TupleTraits<A>::ParamType a,
+    typename TupleTraits<B>::ParamType b,
+    typename TupleTraits<C>::ParamType c,
+    typename TupleTraits<D>::ParamType d,
+    typename TupleTraits<E>::ParamType e,
+    typename TupleTraits<F>::ParamType f,
+    typename TupleTraits<G>::ParamType g,
+    typename TupleTraits<H>::ParamType h)
+    : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) {
+  }
+
+  A a;
+  B b;
+  C c;
+  D d;
+  E e;
+  F f;
+  G g;
+  H h;
+};
+
+// Tuple types ----------------------------------------------------------------
+//
+// Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the
+// definitions of class types the tuple takes as parameters.
+
+template <>
+struct TupleTypes< Tuple0 > {
+  typedef Tuple0 ValueTuple;
+  typedef Tuple0 RefTuple;
+  typedef Tuple0 ParamTuple;
+};
+
+template <class A>
+struct TupleTypes< Tuple1<A> > {
+  typedef Tuple1<typename TupleTraits<A>::ValueType> ValueTuple;
+  typedef Tuple1<typename TupleTraits<A>::RefType> RefTuple;
+  typedef Tuple1<typename TupleTraits<A>::ParamType> ParamTuple;
+};
+
+template <class A, class B>
+struct TupleTypes< Tuple2<A, B> > {
+  typedef Tuple2<typename TupleTraits<A>::ValueType,
+                 typename TupleTraits<B>::ValueType> ValueTuple;
+typedef Tuple2<typename TupleTraits<A>::RefType,
+               typename TupleTraits<B>::RefType> RefTuple;
+  typedef Tuple2<typename TupleTraits<A>::ParamType,
+                 typename TupleTraits<B>::ParamType> ParamTuple;
+};
+
+template <class A, class B, class C>
+struct TupleTypes< Tuple3<A, B, C> > {
+  typedef Tuple3<typename TupleTraits<A>::ValueType,
+                 typename TupleTraits<B>::ValueType,
+                 typename TupleTraits<C>::ValueType> ValueTuple;
+typedef Tuple3<typename TupleTraits<A>::RefType,
+               typename TupleTraits<B>::RefType,
+               typename TupleTraits<C>::RefType> RefTuple;
+  typedef Tuple3<typename TupleTraits<A>::ParamType,
+                 typename TupleTraits<B>::ParamType,
+                 typename TupleTraits<C>::ParamType> ParamTuple;
+};
+
+template <class A, class B, class C, class D>
+struct TupleTypes< Tuple4<A, B, C, D> > {
+  typedef Tuple4<typename TupleTraits<A>::ValueType,
+                 typename TupleTraits<B>::ValueType,
+                 typename TupleTraits<C>::ValueType,
+                 typename TupleTraits<D>::ValueType> ValueTuple;
+typedef Tuple4<typename TupleTraits<A>::RefType,
+               typename TupleTraits<B>::RefType,
+               typename TupleTraits<C>::RefType,
+               typename TupleTraits<D>::RefType> RefTuple;
+  typedef Tuple4<typename TupleTraits<A>::ParamType,
+                 typename TupleTraits<B>::ParamType,
+                 typename TupleTraits<C>::ParamType,
+                 typename TupleTraits<D>::ParamType> ParamTuple;
+};
+
+template <class A, class B, class C, class D, class E>
+struct TupleTypes< Tuple5<A, B, C, D, E> > {
+  typedef Tuple5<typename TupleTraits<A>::ValueType,
+                 typename TupleTraits<B>::ValueType,
+                 typename TupleTraits<C>::ValueType,
+                 typename TupleTraits<D>::ValueType,
+                 typename TupleTraits<E>::ValueType> ValueTuple;
+typedef Tuple5<typename TupleTraits<A>::RefType,
+               typename TupleTraits<B>::RefType,
+               typename TupleTraits<C>::RefType,
+               typename TupleTraits<D>::RefType,
+               typename TupleTraits<E>::RefType> RefTuple;
+  typedef Tuple5<typename TupleTraits<A>::ParamType,
+                 typename TupleTraits<B>::ParamType,
+                 typename TupleTraits<C>::ParamType,
+                 typename TupleTraits<D>::ParamType,
+                 typename TupleTraits<E>::ParamType> ParamTuple;
+};
+
+template <class A, class B, class C, class D, class E, class F>
+struct TupleTypes< Tuple6<A, B, C, D, E, F> > {
+  typedef Tuple6<typename TupleTraits<A>::ValueType,
+                 typename TupleTraits<B>::ValueType,
+                 typename TupleTraits<C>::ValueType,
+                 typename TupleTraits<D>::ValueType,
+                 typename TupleTraits<E>::ValueType,
+                 typename TupleTraits<F>::ValueType> ValueTuple;
+typedef Tuple6<typename TupleTraits<A>::RefType,
+               typename TupleTraits<B>::RefType,
+               typename TupleTraits<C>::RefType,
+               typename TupleTraits<D>::RefType,
+               typename TupleTraits<E>::RefType,
+               typename TupleTraits<F>::RefType> RefTuple;
+  typedef Tuple6<typename TupleTraits<A>::ParamType,
+                 typename TupleTraits<B>::ParamType,
+                 typename TupleTraits<C>::ParamType,
+                 typename TupleTraits<D>::ParamType,
+                 typename TupleTraits<E>::ParamType,
+                 typename TupleTraits<F>::ParamType> ParamTuple;
+};
+
+template <class A, class B, class C, class D, class E, class F, class G>
+struct TupleTypes< Tuple7<A, B, C, D, E, F, G> > {
+  typedef Tuple7<typename TupleTraits<A>::ValueType,
+                 typename TupleTraits<B>::ValueType,
+                 typename TupleTraits<C>::ValueType,
+                 typename TupleTraits<D>::ValueType,
+                 typename TupleTraits<E>::ValueType,
+                 typename TupleTraits<F>::ValueType,
+                 typename TupleTraits<G>::ValueType> ValueTuple;
+typedef Tuple7<typename TupleTraits<A>::RefType,
+               typename TupleTraits<B>::RefType,
+               typename TupleTraits<C>::RefType,
+               typename TupleTraits<D>::RefType,
+               typename TupleTraits<E>::RefType,
+               typename TupleTraits<F>::RefType,
+               typename TupleTraits<G>::RefType> RefTuple;
+  typedef Tuple7<typename TupleTraits<A>::ParamType,
+                 typename TupleTraits<B>::ParamType,
+                 typename TupleTraits<C>::ParamType,
+                 typename TupleTraits<D>::ParamType,
+                 typename TupleTraits<E>::ParamType,
+                 typename TupleTraits<F>::ParamType,
+                 typename TupleTraits<G>::ParamType> ParamTuple;
+};
+
+template <class A, class B, class C, class D, class E, class F, class G,
+          class H>
+struct TupleTypes< Tuple8<A, B, C, D, E, F, G, H> > {
+  typedef Tuple8<typename TupleTraits<A>::ValueType,
+                 typename TupleTraits<B>::ValueType,
+                 typename TupleTraits<C>::ValueType,
+                 typename TupleTraits<D>::ValueType,
+                 typename TupleTraits<E>::ValueType,
+                 typename TupleTraits<F>::ValueType,
+                 typename TupleTraits<G>::ValueType,
+                 typename TupleTraits<H>::ValueType> ValueTuple;
+typedef Tuple8<typename TupleTraits<A>::RefType,
+               typename TupleTraits<B>::RefType,
+               typename TupleTraits<C>::RefType,
+               typename TupleTraits<D>::RefType,
+               typename TupleTraits<E>::RefType,
+               typename TupleTraits<F>::RefType,
+               typename TupleTraits<G>::RefType,
+               typename TupleTraits<H>::RefType> RefTuple;
+  typedef Tuple8<typename TupleTraits<A>::ParamType,
+                 typename TupleTraits<B>::ParamType,
+                 typename TupleTraits<C>::ParamType,
+                 typename TupleTraits<D>::ParamType,
+                 typename TupleTraits<E>::ParamType,
+                 typename TupleTraits<F>::ParamType,
+                 typename TupleTraits<G>::ParamType,
+                 typename TupleTraits<H>::ParamType> ParamTuple;
+};
+
+// Tuple creators -------------------------------------------------------------
+//
+// Helper functions for constructing tuples while inferring the template
+// argument types.
+
+inline Tuple0 MakeTuple() {
+  return Tuple0();
+}
+
+template <class A>
+inline Tuple1<A> MakeTuple(const A& a) {
+  return Tuple1<A>(a);
+}
+
+template <class A, class B>
+inline Tuple2<A, B> MakeTuple(const A& a, const B& b) {
+  return Tuple2<A, B>(a, b);
+}
+
+template <class A, class B, class C>
+inline Tuple3<A, B, C> MakeTuple(const A& a, const B& b, const C& c) {
+  return Tuple3<A, B, C>(a, b, c);
+}
+
+template <class A, class B, class C, class D>
+inline Tuple4<A, B, C, D> MakeTuple(const A& a, const B& b, const C& c,
+                                    const D& d) {
+  return Tuple4<A, B, C, D>(a, b, c, d);
+}
+
+template <class A, class B, class C, class D, class E>
+inline Tuple5<A, B, C, D, E> MakeTuple(const A& a, const B& b, const C& c,
+                                       const D& d, const E& e) {
+  return Tuple5<A, B, C, D, E>(a, b, c, d, e);
+}
+
+template <class A, class B, class C, class D, class E, class F>
+inline Tuple6<A, B, C, D, E, F> MakeTuple(const A& a, const B& b, const C& c,
+                                          const D& d, const E& e, const F& f) {
+  return Tuple6<A, B, C, D, E, F>(a, b, c, d, e, f);
+}
+
+template <class A, class B, class C, class D, class E, class F, class G>
+inline Tuple7<A, B, C, D, E, F, G> MakeTuple(const A& a, const B& b, const C& c,
+                                             const D& d, const E& e, const F& f,
+                                             const G& g) {
+  return Tuple7<A, B, C, D, E, F, G>(a, b, c, d, e, f, g);
+}
+
+template <class A, class B, class C, class D, class E, class F, class G,
+          class H>
+inline Tuple8<A, B, C, D, E, F, G, H> MakeTuple(const A& a, const B& b,
+                                                const C& c, const D& d,
+                                                const E& e, const F& f,
+                                                const G& g, const H& h) {
+  return Tuple8<A, B, C, D, E, F, G, H>(a, b, c, d, e, f, g, h);
+}
+
+// The following set of helpers make what Boost refers to as "Tiers" - a tuple
+// of references.
+
+template <class A>
+inline Tuple1<A&> MakeRefTuple(A& a) {
+  return Tuple1<A&>(a);
+}
+
+template <class A, class B>
+inline Tuple2<A&, B&> MakeRefTuple(A& a, B& b) {
+  return Tuple2<A&, B&>(a, b);
+}
+
+template <class A, class B, class C>
+inline Tuple3<A&, B&, C&> MakeRefTuple(A& a, B& b, C& c) {
+  return Tuple3<A&, B&, C&>(a, b, c);
+}
+
+template <class A, class B, class C, class D>
+inline Tuple4<A&, B&, C&, D&> MakeRefTuple(A& a, B& b, C& c, D& d) {
+  return Tuple4<A&, B&, C&, D&>(a, b, c, d);
+}
+
+template <class A, class B, class C, class D, class E>
+inline Tuple5<A&, B&, C&, D&, E&> MakeRefTuple(A& a, B& b, C& c, D& d, E& e) {
+  return Tuple5<A&, B&, C&, D&, E&>(a, b, c, d, e);
+}
+
+template <class A, class B, class C, class D, class E, class F>
+inline Tuple6<A&, B&, C&, D&, E&, F&> MakeRefTuple(A& a, B& b, C& c, D& d, E& e,
+                                                   F& f) {
+  return Tuple6<A&, B&, C&, D&, E&, F&>(a, b, c, d, e, f);
+}
+
+template <class A, class B, class C, class D, class E, class F, class G>
+inline Tuple7<A&, B&, C&, D&, E&, F&, G&> MakeRefTuple(A& a, B& b, C& c, D& d,
+                                                       E& e, F& f, G& g) {
+  return Tuple7<A&, B&, C&, D&, E&, F&, G&>(a, b, c, d, e, f, g);
+}
+
+template <class A, class B, class C, class D, class E, class F, class G,
+          class H>
+inline Tuple8<A&, B&, C&, D&, E&, F&, G&, H&> MakeRefTuple(A& a, B& b, C& c,
+                                                           D& d, E& e, F& f,
+                                                           G& g, H& h) {
+  return Tuple8<A&, B&, C&, D&, E&, F&, G&, H&>(a, b, c, d, e, f, g, h);
+}
+
+// Dispatchers ----------------------------------------------------------------
+//
+// Helper functions that call the given method on an object, with the unpacked
+// tuple arguments.  Notice that they all have the same number of arguments,
+// so you need only write:
+//   DispatchToMethod(object, &Object::method, args);
+// This is very useful for templated dispatchers, since they don't need to know
+// what type |args| is.
+
+// Non-Static Dispatchers with no out params.
+
+template <class ObjT, class Method>
+inline void DispatchToMethod(ObjT* obj, Method method, const Tuple0& arg) {
+  (obj->*method)();
+}
+
+template <class ObjT, class Method, class A>
+inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) {
+  (obj->*method)(arg);
+}
+
+template <class ObjT, class Method, class A>
+inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1<A>& arg) {
+  (obj->*method)(arg.a);
+}
+
+template<class ObjT, class Method, class A, class B>
+inline void DispatchToMethod(ObjT* obj,
+                             Method method,
+                             const Tuple2<A, B>& arg) {
+  (obj->*method)(arg.a, arg.b);
+}
+
+template<class ObjT, class Method, class A, class B, class C>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple3<A, B, C>& arg) {
+  (obj->*method)(arg.a, arg.b, arg.c);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple4<A, B, C, D>& arg) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D, class E>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple5<A, B, C, D, E>& arg) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D, class E,
+         class F>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple6<A, B, C, D, E, F>& arg) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D, class E,
+         class F, class G>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple7<A, B, C, D, E, F, G>& arg) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D, class E,
+         class F, class G, class H>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple8<A, B, C, D, E, F, G, H>& arg) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g, arg.h);
+}
+
+// Static Dispatchers with no out params.
+
+template <class Function>
+inline void DispatchToFunction(Function function, const Tuple0& arg) {
+  (*function)();
+}
+
+template <class Function, class A>
+inline void DispatchToFunction(Function function, const A& arg) {
+  (*function)(arg);
+}
+
+template <class Function, class A>
+inline void DispatchToFunction(Function function, const Tuple1<A>& arg) {
+  (*function)(arg.a);
+}
+
+template<class Function, class A, class B>
+inline void DispatchToFunction(Function function, const Tuple2<A, B>& arg) {
+  (*function)(arg.a, arg.b);
+}
+
+template<class Function, class A, class B, class C>
+inline void DispatchToFunction(Function function, const Tuple3<A, B, C>& arg) {
+  (*function)(arg.a, arg.b, arg.c);
+}
+
+template<class Function, class A, class B, class C, class D>
+inline void DispatchToFunction(Function function,
+                               const Tuple4<A, B, C, D>& arg) {
+  (*function)(arg.a, arg.b, arg.c, arg.d);
+}
+
+template<class Function, class A, class B, class C, class D, class E>
+inline void DispatchToFunction(Function function,
+                               const Tuple5<A, B, C, D, E>& arg) {
+  (*function)(arg.a, arg.b, arg.c, arg.d, arg.e);
+}
+
+template<class Function, class A, class B, class C, class D, class E, class F>
+inline void DispatchToFunction(Function function,
+                               const Tuple6<A, B, C, D, E, F>& arg) {
+  (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f);
+}
+
+template<class Function, class A, class B, class C, class D, class E, class F,
+         class G>
+inline void DispatchToFunction(Function function,
+                               const Tuple7<A, B, C, D, E, F, G>& arg) {
+  (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g);
+}
+
+template<class Function, class A, class B, class C, class D, class E, class F,
+         class G, class H>
+inline void DispatchToFunction(Function function,
+                               const Tuple8<A, B, C, D, E, F, G, H>& arg) {
+  (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g, arg.h);
+}
+
+// Dispatchers with 0 out param (as a Tuple0).
+
+template <class ObjT, class Method>
+inline void DispatchToMethod(ObjT* obj,
+                             Method method,
+                             const Tuple0& arg, Tuple0*) {
+  (obj->*method)();
+}
+
+template <class ObjT, class Method, class A>
+inline void DispatchToMethod(ObjT* obj, Method method, const A& arg, Tuple0*) {
+  (obj->*method)(arg);
+}
+
+template <class ObjT, class Method, class A>
+inline void DispatchToMethod(ObjT* obj,
+                             Method method,
+                             const Tuple1<A>& arg, Tuple0*) {
+  (obj->*method)(arg.a);
+}
+
+template<class ObjT, class Method, class A, class B>
+inline void DispatchToMethod(ObjT* obj,
+                             Method method,
+                             const Tuple2<A, B>& arg, Tuple0*) {
+  (obj->*method)(arg.a, arg.b);
+}
+
+template<class ObjT, class Method, class A, class B, class C>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple3<A, B, C>& arg, Tuple0*) {
+  (obj->*method)(arg.a, arg.b, arg.c);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple4<A, B, C, D>& arg, Tuple0*) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D, class E>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple5<A, B, C, D, E>& arg, Tuple0*) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D, class E,
+         class F>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple6<A, B, C, D, E, F>& arg, Tuple0*) {
+  (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f);
+}
+
+// Dispatchers with 1 out param.
+
+template<class ObjT, class Method,
+         class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple0& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(&out->a);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const InA& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(in, &out->a);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple1<InA>& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(in.a, &out->a);
+}
+
+template<class ObjT, class Method, class InA, class InB,
+         class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple2<InA, InB>& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(in.a, in.b, &out->a);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC,
+         class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple3<InA, InB, InC>& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(in.a, in.b, in.c, &out->a);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC, class InD,
+         class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple4<InA, InB, InC, InD>& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, &out->a);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC, class InD,
+         class InE, class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple5<InA, InB, InC, InD, InE>& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE, class InF,
+         class OutA>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
+                             Tuple1<OutA>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a);
+}
+
+// Dispatchers with 2 out params.
+
+template<class ObjT, class Method,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple0& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(&out->a, &out->b);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const InA& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(in, &out->a, &out->b);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple1<InA>& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(in.a, &out->a, &out->b);
+}
+
+template<class ObjT, class Method, class InA, class InB,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple2<InA, InB>& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(in.a, in.b, &out->a, &out->b);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple3<InA, InB, InC>& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(in.a, in.b, in.c, &out->a, &out->b);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC, class InD,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple4<InA, InB, InC, InD>& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple5<InA, InB, InC, InD, InE>& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE, class InF,
+         class OutA, class OutB>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
+                             Tuple2<OutA, OutB>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b);
+}
+
+// Dispatchers with 3 out params.
+
+template<class ObjT, class Method,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple0& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(&out->a, &out->b, &out->c);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const InA& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(in, &out->a, &out->b, &out->c);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple1<InA>& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(in.a, &out->a, &out->b, &out->c);
+}
+
+template<class ObjT, class Method, class InA, class InB,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple2<InA, InB>& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple3<InA, InB, InC>& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC, class InD,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple4<InA, InB, InC, InD>& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple5<InA, InB, InC, InD, InE>& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b, &out->c);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE, class InF,
+         class OutA, class OutB, class OutC>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
+                             Tuple3<OutA, OutB, OutC>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b, &out->c);
+}
+
+// Dispatchers with 4 out params.
+
+template<class ObjT, class Method,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple0& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(&out->a, &out->b, &out->c, &out->d);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const InA& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(in, &out->a, &out->b, &out->c, &out->d);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple1<InA>& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d);
+}
+
+template<class ObjT, class Method, class InA, class InB,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple2<InA, InB>& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple3<InA, InB, InC>& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC, class InD,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple4<InA, InB, InC, InD>& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple5<InA, InB, InC, InD, InE>& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e,
+                 &out->a, &out->b, &out->c, &out->d);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE, class InF,
+         class OutA, class OutB, class OutC, class OutD>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
+                             Tuple4<OutA, OutB, OutC, OutD>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f,
+                 &out->a, &out->b, &out->c, &out->d);
+}
+
+// Dispatchers with 5 out params.
+
+template<class ObjT, class Method,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple0& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(&out->a, &out->b, &out->c, &out->d, &out->e);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const InA& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(in, &out->a, &out->b, &out->c, &out->d, &out->e);
+}
+
+template<class ObjT, class Method, class InA,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple1<InA>& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d, &out->e);
+}
+
+template<class ObjT, class Method, class InA, class InB,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple2<InA, InB>& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d, &out->e);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple3<InA, InB, InC>& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d, &out->e);
+}
+
+template<class ObjT, class Method, class InA, class InB, class InC, class InD,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple4<InA, InB, InC, InD>& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d,
+                 &out->e);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple5<InA, InB, InC, InD, InE>& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e,
+                 &out->a, &out->b, &out->c, &out->d, &out->e);
+}
+
+template<class ObjT, class Method,
+         class InA, class InB, class InC, class InD, class InE, class InF,
+         class OutA, class OutB, class OutC, class OutD, class OutE>
+inline void DispatchToMethod(ObjT* obj, Method method,
+                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
+                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
+  (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f,
+                 &out->a, &out->b, &out->c, &out->d, &out->e);
+}
+
+#endif  // BASE_TUPLE_H__
diff --git a/base/values.cc b/base/values.cc
new file mode 100644 (file)
index 0000000..7a364bd
--- /dev/null
@@ -0,0 +1,905 @@
+// 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/logging.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+
+namespace {
+
+// Make a deep copy of |node|, but don't include empty lists or dictionaries
+// in the copy. It's possible for this function to return NULL and it
+// expects |node| to always be non-NULL.
+Value* CopyWithoutEmptyChildren(Value* node) {
+  DCHECK(node);
+  switch (node->GetType()) {
+    case Value::TYPE_LIST: {
+      ListValue* list = static_cast<ListValue*>(node);
+      ListValue* copy = new ListValue;
+      for (ListValue::const_iterator it = list->begin(); it != list->end();
+           ++it) {
+        Value* child_copy = CopyWithoutEmptyChildren(*it);
+        if (child_copy)
+          copy->Append(child_copy);
+      }
+      if (!copy->empty())
+        return copy;
+
+      delete copy;
+      return NULL;
+    }
+
+    case Value::TYPE_DICTIONARY: {
+      DictionaryValue* dict = static_cast<DictionaryValue*>(node);
+      DictionaryValue* copy = new DictionaryValue;
+      for (DictionaryValue::key_iterator it = dict->begin_keys();
+           it != dict->end_keys(); ++it) {
+        Value* child = NULL;
+        bool rv = dict->GetWithoutPathExpansion(*it, &child);
+        DCHECK(rv);
+        Value* child_copy = CopyWithoutEmptyChildren(child);
+        if (child_copy)
+          copy->SetWithoutPathExpansion(*it, child_copy);
+      }
+      if (!copy->empty())
+        return copy;
+
+      delete copy;
+      return NULL;
+    }
+
+    default:
+      // For everything else, just make a copy.
+      return node->DeepCopy();
+  }
+}
+
+}  // namespace
+
+namespace base {
+
+///////////////////// Value ////////////////////
+
+Value::~Value() {
+}
+
+// static
+Value* Value::CreateNullValue() {
+  return new Value(TYPE_NULL);
+}
+
+// static
+FundamentalValue* Value::CreateBooleanValue(bool in_value) {
+  return new FundamentalValue(in_value);
+}
+
+// static
+FundamentalValue* Value::CreateIntegerValue(int in_value) {
+  return new FundamentalValue(in_value);
+}
+
+// static
+FundamentalValue* Value::CreateDoubleValue(double in_value) {
+  return new FundamentalValue(in_value);
+}
+
+// static
+StringValue* Value::CreateStringValue(const std::string& in_value) {
+  return new StringValue(in_value);
+}
+
+// static
+StringValue* Value::CreateStringValue(const string16& in_value) {
+  return new StringValue(in_value);
+}
+
+bool Value::GetAsBoolean(bool* out_value) const {
+  return false;
+}
+
+bool Value::GetAsInteger(int* out_value) const {
+  return false;
+}
+
+bool Value::GetAsDouble(double* out_value) const {
+  return false;
+}
+
+bool Value::GetAsString(std::string* out_value) const {
+  return false;
+}
+
+bool Value::GetAsString(string16* out_value) const {
+  return false;
+}
+
+bool Value::GetAsList(ListValue** out_value) {
+  return false;
+}
+
+bool Value::GetAsList(const ListValue** out_value) const {
+  return false;
+}
+
+Value* Value::DeepCopy() const {
+  // This method should only be getting called for null Values--all subclasses
+  // need to provide their own implementation;.
+  DCHECK(IsType(TYPE_NULL));
+  return CreateNullValue();
+}
+
+bool Value::Equals(const Value* other) const {
+  // This method should only be getting called for null Values--all subclasses
+  // need to provide their own implementation;.
+  DCHECK(IsType(TYPE_NULL));
+  return other->IsType(TYPE_NULL);
+}
+
+// static
+bool Value::Equals(const Value* a, const Value* b) {
+  if ((a == NULL) && (b == NULL)) return true;
+  if ((a == NULL) ^  (b == NULL)) return false;
+  return a->Equals(b);
+}
+
+Value::Value(Type type) : type_(type) {
+}
+
+///////////////////// FundamentalValue ////////////////////
+
+FundamentalValue::FundamentalValue(bool in_value)
+    : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
+}
+
+FundamentalValue::FundamentalValue(int in_value)
+    : Value(TYPE_INTEGER), integer_value_(in_value) {
+}
+
+FundamentalValue::FundamentalValue(double in_value)
+    : Value(TYPE_DOUBLE), double_value_(in_value) {
+}
+
+FundamentalValue::~FundamentalValue() {
+}
+
+bool FundamentalValue::GetAsBoolean(bool* out_value) const {
+  if (out_value && IsType(TYPE_BOOLEAN))
+    *out_value = boolean_value_;
+  return (IsType(TYPE_BOOLEAN));
+}
+
+bool FundamentalValue::GetAsInteger(int* out_value) const {
+  if (out_value && IsType(TYPE_INTEGER))
+    *out_value = integer_value_;
+  return (IsType(TYPE_INTEGER));
+}
+
+bool FundamentalValue::GetAsDouble(double* out_value) const {
+  if (out_value && IsType(TYPE_DOUBLE))
+    *out_value = double_value_;
+  else if (out_value && IsType(TYPE_INTEGER))
+    *out_value = integer_value_;
+  return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER));
+}
+
+FundamentalValue* FundamentalValue::DeepCopy() const {
+  switch (GetType()) {
+    case TYPE_BOOLEAN:
+      return CreateBooleanValue(boolean_value_);
+
+    case TYPE_INTEGER:
+      return CreateIntegerValue(integer_value_);
+
+    case TYPE_DOUBLE:
+      return CreateDoubleValue(double_value_);
+
+    default:
+      NOTREACHED();
+      return NULL;
+  }
+}
+
+bool FundamentalValue::Equals(const Value* other) const {
+  if (other->GetType() != GetType())
+    return false;
+
+  switch (GetType()) {
+    case TYPE_BOOLEAN: {
+      bool lhs, rhs;
+      return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
+    }
+    case TYPE_INTEGER: {
+      int lhs, rhs;
+      return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
+    }
+    case TYPE_DOUBLE: {
+      double lhs, rhs;
+      return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
+    }
+    default:
+      NOTREACHED();
+      return false;
+  }
+}
+
+///////////////////// StringValue ////////////////////
+
+StringValue::StringValue(const std::string& in_value)
+    : Value(TYPE_STRING),
+      value_(in_value) {
+  DCHECK(IsStringUTF8(in_value));
+}
+
+StringValue::StringValue(const string16& in_value)
+    : Value(TYPE_STRING),
+      value_(UTF16ToUTF8(in_value)) {
+}
+
+StringValue::~StringValue() {
+}
+
+bool StringValue::GetAsString(std::string* out_value) const {
+  if (out_value)
+    *out_value = value_;
+  return true;
+}
+
+bool StringValue::GetAsString(string16* out_value) const {
+  if (out_value)
+    *out_value = UTF8ToUTF16(value_);
+  return true;
+}
+
+StringValue* StringValue::DeepCopy() const {
+  return CreateStringValue(value_);
+}
+
+bool StringValue::Equals(const Value* other) const {
+  if (other->GetType() != GetType())
+    return false;
+  std::string lhs, rhs;
+  return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
+}
+
+///////////////////// BinaryValue ////////////////////
+
+BinaryValue::~BinaryValue() {
+  DCHECK(buffer_);
+  if (buffer_)
+    delete[] buffer_;
+}
+
+// static
+BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
+  if (!buffer)
+    return NULL;
+
+  return new BinaryValue(buffer, size);
+}
+
+// static
+BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
+                                                 size_t size) {
+  if (!buffer)
+    return NULL;
+
+  char* buffer_copy = new char[size];
+  memcpy(buffer_copy, buffer, size);
+  return new BinaryValue(buffer_copy, size);
+}
+
+BinaryValue* BinaryValue::DeepCopy() const {
+  return CreateWithCopiedBuffer(buffer_, size_);
+}
+
+bool BinaryValue::Equals(const Value* other) const {
+  if (other->GetType() != GetType())
+    return false;
+  const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
+  if (other_binary->size_ != size_)
+    return false;
+  return !memcmp(buffer_, other_binary->buffer_, size_);
+}
+
+BinaryValue::BinaryValue(char* buffer, size_t size)
+  : Value(TYPE_BINARY),
+    buffer_(buffer),
+    size_(size) {
+  DCHECK(buffer_);
+}
+
+///////////////////// DictionaryValue ////////////////////
+
+DictionaryValue::DictionaryValue()
+    : Value(TYPE_DICTIONARY) {
+}
+
+DictionaryValue::~DictionaryValue() {
+  Clear();
+}
+
+bool DictionaryValue::HasKey(const std::string& key) const {
+  DCHECK(IsStringUTF8(key));
+  ValueMap::const_iterator current_entry = dictionary_.find(key);
+  DCHECK((current_entry == dictionary_.end()) || current_entry->second);
+  return current_entry != dictionary_.end();
+}
+
+void DictionaryValue::Clear() {
+  ValueMap::iterator dict_iterator = dictionary_.begin();
+  while (dict_iterator != dictionary_.end()) {
+    delete dict_iterator->second;
+    ++dict_iterator;
+  }
+
+  dictionary_.clear();
+}
+
+void DictionaryValue::Set(const std::string& path, Value* in_value) {
+  DCHECK(IsStringUTF8(path));
+  DCHECK(in_value);
+
+  std::string current_path(path);
+  DictionaryValue* current_dictionary = this;
+  for (size_t delimiter_position = current_path.find('.');
+       delimiter_position != std::string::npos;
+       delimiter_position = current_path.find('.')) {
+    // Assume that we're indexing into a dictionary.
+    std::string key(current_path, 0, delimiter_position);
+    DictionaryValue* child_dictionary = NULL;
+    if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
+      child_dictionary = new DictionaryValue;
+      current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
+    }
+
+    current_dictionary = child_dictionary;
+    current_path.erase(0, delimiter_position + 1);
+  }
+
+  current_dictionary->SetWithoutPathExpansion(current_path, in_value);
+}
+
+void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
+  Set(path, CreateBooleanValue(in_value));
+}
+
+void DictionaryValue::SetInteger(const std::string& path, int in_value) {
+  Set(path, CreateIntegerValue(in_value));
+}
+
+void DictionaryValue::SetDouble(const std::string& path, double in_value) {
+  Set(path, CreateDoubleValue(in_value));
+}
+
+void DictionaryValue::SetString(const std::string& path,
+                                const std::string& in_value) {
+  Set(path, CreateStringValue(in_value));
+}
+
+void DictionaryValue::SetString(const std::string& path,
+                                const string16& in_value) {
+  Set(path, CreateStringValue(in_value));
+}
+
+void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
+                                              Value* in_value) {
+  // If there's an existing value here, we need to delete it, because
+  // we own all our children.
+  if (HasKey(key)) {
+    DCHECK(dictionary_[key] != in_value);  // This would be bogus
+    delete dictionary_[key];
+  }
+
+  dictionary_[key] = in_value;
+}
+
+bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
+  DCHECK(IsStringUTF8(path));
+  std::string current_path(path);
+  const DictionaryValue* current_dictionary = this;
+  for (size_t delimiter_position = current_path.find('.');
+       delimiter_position != std::string::npos;
+       delimiter_position = current_path.find('.')) {
+    DictionaryValue* child_dictionary = NULL;
+    if (!current_dictionary->GetDictionary(
+            current_path.substr(0, delimiter_position), &child_dictionary))
+      return false;
+
+    current_dictionary = child_dictionary;
+    current_path.erase(0, delimiter_position + 1);
+  }
+
+  return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
+}
+
+bool DictionaryValue::GetBoolean(const std::string& path,
+                                 bool* bool_value) const {
+  Value* value;
+  if (!Get(path, &value))
+    return false;
+
+  return value->GetAsBoolean(bool_value);
+}
+
+bool DictionaryValue::GetInteger(const std::string& path,
+                                 int* out_value) const {
+  Value* value;
+  if (!Get(path, &value))
+    return false;
+
+  return value->GetAsInteger(out_value);
+}
+
+bool DictionaryValue::GetDouble(const std::string& path,
+                                double* out_value) const {
+  Value* value;
+  if (!Get(path, &value))
+    return false;
+
+  return value->GetAsDouble(out_value);
+}
+
+bool DictionaryValue::GetString(const std::string& path,
+                                std::string* out_value) const {
+  Value* value;
+  if (!Get(path, &value))
+    return false;
+
+  return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetString(const std::string& path,
+                                string16* out_value) const {
+  Value* value;
+  if (!Get(path, &value))
+    return false;
+
+  return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetStringASCII(const std::string& path,
+                                     std::string* out_value) const {
+  std::string out;
+  if (!GetString(path, &out))
+    return false;
+
+  if (!IsStringASCII(out)) {
+    NOTREACHED();
+    return false;
+  }
+
+  out_value->assign(out);
+  return true;
+}
+
+bool DictionaryValue::GetBinary(const std::string& path,
+                                BinaryValue** out_value) const {
+  Value* value;
+  bool result = Get(path, &value);
+  if (!result || !value->IsType(TYPE_BINARY))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<BinaryValue*>(value);
+
+  return true;
+}
+
+bool DictionaryValue::GetDictionary(const std::string& path,
+                                    DictionaryValue** out_value) const {
+  Value* value;
+  bool result = Get(path, &value);
+  if (!result || !value->IsType(TYPE_DICTIONARY))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<DictionaryValue*>(value);
+
+  return true;
+}
+
+bool DictionaryValue::GetList(const std::string& path,
+                              ListValue** out_value) const {
+  Value* value;
+  bool result = Get(path, &value);
+  if (!result || !value->IsType(TYPE_LIST))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<ListValue*>(value);
+
+  return true;
+}
+
+bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
+                                              Value** out_value) const {
+  DCHECK(IsStringUTF8(key));
+  ValueMap::const_iterator entry_iterator = dictionary_.find(key);
+  if (entry_iterator == dictionary_.end())
+    return false;
+
+  Value* entry = entry_iterator->second;
+  if (out_value)
+    *out_value = entry;
+  return true;
+}
+
+bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
+                                                     int* out_value) const {
+  Value* value;
+  if (!GetWithoutPathExpansion(key, &value))
+    return false;
+
+  return value->GetAsInteger(out_value);
+}
+
+bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
+                                                    double* out_value) const {
+  Value* value;
+  if (!GetWithoutPathExpansion(key, &value))
+    return false;
+
+  return value->GetAsDouble(out_value);
+}
+
+bool DictionaryValue::GetStringWithoutPathExpansion(
+    const std::string& key,
+    std::string* out_value) const {
+  Value* value;
+  if (!GetWithoutPathExpansion(key, &value))
+    return false;
+
+  return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetStringWithoutPathExpansion(
+    const std::string& key,
+    string16* out_value) const {
+  Value* value;
+  if (!GetWithoutPathExpansion(key, &value))
+    return false;
+
+  return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetDictionaryWithoutPathExpansion(
+    const std::string& key,
+    DictionaryValue** out_value) const {
+  Value* value;
+  bool result = GetWithoutPathExpansion(key, &value);
+  if (!result || !value->IsType(TYPE_DICTIONARY))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<DictionaryValue*>(value);
+
+  return true;
+}
+
+bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
+                                                  ListValue** out_value) const {
+  Value* value;
+  bool result = GetWithoutPathExpansion(key, &value);
+  if (!result || !value->IsType(TYPE_LIST))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<ListValue*>(value);
+
+  return true;
+}
+
+bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
+  DCHECK(IsStringUTF8(path));
+  std::string current_path(path);
+  DictionaryValue* current_dictionary = this;
+  size_t delimiter_position = current_path.rfind('.');
+  if (delimiter_position != std::string::npos) {
+    if (!GetDictionary(current_path.substr(0, delimiter_position),
+                       &current_dictionary))
+      return false;
+    current_path.erase(0, delimiter_position + 1);
+  }
+
+  return current_dictionary->RemoveWithoutPathExpansion(current_path,
+                                                        out_value);
+}
+
+bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
+                                                 Value** out_value) {
+  DCHECK(IsStringUTF8(key));
+  ValueMap::iterator entry_iterator = dictionary_.find(key);
+  if (entry_iterator == dictionary_.end())
+    return false;
+
+  Value* entry = entry_iterator->second;
+  if (out_value)
+    *out_value = entry;
+  else
+    delete entry;
+  dictionary_.erase(entry_iterator);
+  return true;
+}
+
+DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
+  Value* copy = CopyWithoutEmptyChildren(this);
+  return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
+}
+
+void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
+  for (DictionaryValue::key_iterator key(dictionary->begin_keys());
+       key != dictionary->end_keys(); ++key) {
+    Value* merge_value;
+    if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
+      // Check whether we have to merge dictionaries.
+      if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
+        DictionaryValue* sub_dict;
+        if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
+          sub_dict->MergeDictionary(
+              static_cast<const DictionaryValue*>(merge_value));
+          continue;
+        }
+      }
+      // All other cases: Make a copy and hook it up.
+      SetWithoutPathExpansion(*key, merge_value->DeepCopy());
+    }
+  }
+}
+
+DictionaryValue* DictionaryValue::DeepCopy() const {
+  DictionaryValue* result = new DictionaryValue;
+
+  for (ValueMap::const_iterator current_entry(dictionary_.begin());
+       current_entry != dictionary_.end(); ++current_entry) {
+    result->SetWithoutPathExpansion(current_entry->first,
+                                    current_entry->second->DeepCopy());
+  }
+
+  return result;
+}
+
+bool DictionaryValue::Equals(const Value* other) const {
+  if (other->GetType() != GetType())
+    return false;
+
+  const DictionaryValue* other_dict =
+      static_cast<const DictionaryValue*>(other);
+  key_iterator lhs_it(begin_keys());
+  key_iterator rhs_it(other_dict->begin_keys());
+  while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
+    Value* lhs;
+    Value* rhs;
+    if (*lhs_it != *rhs_it ||
+        !GetWithoutPathExpansion(*lhs_it, &lhs) ||
+        !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
+        !lhs->Equals(rhs)) {
+      return false;
+    }
+    ++lhs_it;
+    ++rhs_it;
+  }
+  if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
+    return false;
+
+  return true;
+}
+
+///////////////////// ListValue ////////////////////
+
+ListValue::ListValue() : Value(TYPE_LIST) {
+}
+
+ListValue::~ListValue() {
+  Clear();
+}
+
+void ListValue::Clear() {
+  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
+    delete *i;
+  list_.clear();
+}
+
+bool ListValue::Set(size_t index, Value* in_value) {
+  if (!in_value)
+    return false;
+
+  if (index >= list_.size()) {
+    // Pad out any intermediate indexes with null settings
+    while (index > list_.size())
+      Append(CreateNullValue());
+    Append(in_value);
+  } else {
+    DCHECK(list_[index] != in_value);
+    delete list_[index];
+    list_[index] = in_value;
+  }
+  return true;
+}
+
+bool ListValue::Get(size_t index, Value** out_value) const {
+  if (index >= list_.size())
+    return false;
+
+  if (out_value)
+    *out_value = list_[index];
+
+  return true;
+}
+
+bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
+  Value* value;
+  if (!Get(index, &value))
+    return false;
+
+  return value->GetAsBoolean(bool_value);
+}
+
+bool ListValue::GetInteger(size_t index, int* out_value) const {
+  Value* value;
+  if (!Get(index, &value))
+    return false;
+
+  return value->GetAsInteger(out_value);
+}
+
+bool ListValue::GetDouble(size_t index, double* out_value) const {
+  Value* value;
+  if (!Get(index, &value))
+    return false;
+
+  return value->GetAsDouble(out_value);
+}
+
+bool ListValue::GetString(size_t index, std::string* out_value) const {
+  Value* value;
+  if (!Get(index, &value))
+    return false;
+
+  return value->GetAsString(out_value);
+}
+
+bool ListValue::GetString(size_t index, string16* out_value) const {
+  Value* value;
+  if (!Get(index, &value))
+    return false;
+
+  return value->GetAsString(out_value);
+}
+
+bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
+  Value* value;
+  bool result = Get(index, &value);
+  if (!result || !value->IsType(TYPE_BINARY))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<BinaryValue*>(value);
+
+  return true;
+}
+
+bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
+  Value* value;
+  bool result = Get(index, &value);
+  if (!result || !value->IsType(TYPE_DICTIONARY))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<DictionaryValue*>(value);
+
+  return true;
+}
+
+bool ListValue::GetList(size_t index, ListValue** out_value) const {
+  Value* value;
+  bool result = Get(index, &value);
+  if (!result || !value->IsType(TYPE_LIST))
+    return false;
+
+  if (out_value)
+    *out_value = static_cast<ListValue*>(value);
+
+  return true;
+}
+
+bool ListValue::Remove(size_t index, Value** out_value) {
+  if (index >= list_.size())
+    return false;
+
+  if (out_value)
+    *out_value = list_[index];
+  else
+    delete list_[index];
+
+  list_.erase(list_.begin() + index);
+  return true;
+}
+
+bool ListValue::Remove(const Value& value, size_t* index) {
+  for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
+    if ((*i)->Equals(&value)) {
+      size_t previous_index = i - list_.begin();
+      delete *i;
+      list_.erase(i);
+
+      if (index)
+        *index = previous_index;
+      return true;
+    }
+  }
+  return false;
+}
+
+void ListValue::Append(Value* in_value) {
+  DCHECK(in_value);
+  list_.push_back(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)) {
+      delete in_value;
+      return false;
+    }
+  }
+  list_.push_back(in_value);
+  return true;
+}
+
+bool ListValue::Insert(size_t index, Value* in_value) {
+  DCHECK(in_value);
+  if (index > list_.size())
+    return false;
+
+  list_.insert(list_.begin() + index, in_value);
+  return true;
+}
+
+bool ListValue::GetAsList(ListValue** out_value) {
+  if (out_value)
+    *out_value = this;
+  return true;
+}
+
+bool ListValue::GetAsList(const ListValue** out_value) const {
+  if (out_value)
+    *out_value = this;
+  return true;
+}
+
+ListValue* ListValue::DeepCopy() const {
+  ListValue* result = new ListValue;
+
+  for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
+    result->Append((*i)->DeepCopy());
+
+  return result;
+}
+
+bool ListValue::Equals(const Value* other) const {
+  if (other->GetType() != GetType())
+    return false;
+
+  const ListValue* other_list =
+      static_cast<const ListValue*>(other);
+  const_iterator lhs_it, rhs_it;
+  for (lhs_it = begin(), rhs_it = other_list->begin();
+       lhs_it != end() && rhs_it != other_list->end();
+       ++lhs_it, ++rhs_it) {
+    if (!(*lhs_it)->Equals(*rhs_it))
+      return false;
+  }
+  if (lhs_it != end() || rhs_it != other_list->end())
+    return false;
+
+  return true;
+}
+
+ValueSerializer::~ValueSerializer() {
+}
+
+}  // namespace base
diff --git a/base/values.h b/base/values.h
new file mode 100644 (file)
index 0000000..a30791b
--- /dev/null
@@ -0,0 +1,470 @@
+// 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 specifies a recursive data storage class called Value intended for
+// storing setting and other persistable data.  It includes the ability to
+// specify (recursive) lists and dictionaries, so it's fairly expressive.
+// However, the API is optimized for the common case, namely storing a
+// hierarchical tree of simple values.  Given a DictionaryValue root, you can
+// easily do things like:
+//
+// root->SetString("global.pages.homepage", "http://goateleporter.com");
+// std::string homepage = "http://google.com";  // default/fallback value
+// root->GetString("global.pages.homepage", &homepage);
+//
+// where "global" and "pages" are also DictionaryValues, and "homepage" is a
+// string setting.  If some elements of the path didn't exist yet, the
+// SetString() method would create the missing elements and attach them to root
+// before attaching the homepage value.
+
+#ifndef BASE_VALUES_H_
+#define BASE_VALUES_H_
+#pragma once
+
+#include <iterator>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/string16.h"
+
+// This file declares "using base::Value", etc. at the bottom, so that
+// current code can use these classes without the base namespace. In
+// new code, please always use base::Value, etc. or add your own
+// "using" declaration.
+// http://crbug.com/88666
+namespace base {
+
+class BinaryValue;
+class DictionaryValue;
+class FundamentalValue;
+class ListValue;
+class StringValue;
+class Value;
+
+typedef std::vector<Value*> ValueVector;
+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 BASE_EXPORT Value {
+ public:
+  enum Type {
+    TYPE_NULL = 0,
+    TYPE_BOOLEAN,
+    TYPE_INTEGER,
+    TYPE_DOUBLE,
+    TYPE_STRING,
+    TYPE_BINARY,
+    TYPE_DICTIONARY,
+    TYPE_LIST
+  };
+
+  virtual ~Value();
+
+  // Convenience methods for creating Value objects for various
+  // kinds of values without thinking about which class implements them.
+  // These can always be expected to return a valid Value*.
+  static Value* CreateNullValue();
+  static FundamentalValue* CreateBooleanValue(bool in_value);
+  static FundamentalValue* CreateIntegerValue(int in_value);
+  static FundamentalValue* CreateDoubleValue(double in_value);
+  static StringValue* CreateStringValue(const std::string& in_value);
+  static StringValue* CreateStringValue(const string16& in_value);
+
+  // Returns the type of the value stored by the current Value object.
+  // Each type will be implemented by only one subclass of Value, so it's
+  // safe to use the Type to determine whether you can cast from
+  // Value* to (Implementing Class)*.  Also, a Value object never changes
+  // its type after construction.
+  Type GetType() const { return type_; }
+
+  // Returns true if the current object represents a given type.
+  bool IsType(Type type) const { return type == type_; }
+
+  // These methods allow the convenient retrieval of settings.
+  // If the current setting object can be converted into the given type,
+  // the value is returned through the |out_value| parameter and true is
+  // returned;  otherwise, false is returned and |out_value| is unchanged.
+  virtual bool GetAsBoolean(bool* out_value) const;
+  virtual bool GetAsInteger(int* out_value) const;
+  virtual bool GetAsDouble(double* out_value) const;
+  virtual bool GetAsString(std::string* out_value) const;
+  virtual bool GetAsString(string16* out_value) const;
+  virtual bool GetAsList(ListValue** out_value);
+  virtual bool GetAsList(const ListValue** out_value) const;
+
+  // This creates a deep copy of the entire Value tree, and returns a pointer
+  // to the copy.  The caller gets ownership of the copy, of course.
+  //
+  // Subclasses return their own type directly in their overrides;
+  // this works because C++ supports covariant return types.
+  virtual Value* DeepCopy() const;
+
+  // Compares if two Value objects have equal contents.
+  virtual bool Equals(const Value* other) const;
+
+  // Compares if two Value objects have equal contents. Can handle NULLs.
+  // NULLs are considered equal but different from Value::CreateNullValue().
+  static bool Equals(const Value* a, const Value* b);
+
+ protected:
+  // This isn't safe for end-users (they should use the Create*Value()
+  // static methods above), but it's useful for subclasses.
+  explicit Value(Type type);
+
+ private:
+  Value();
+
+  Type type_;
+
+  DISALLOW_COPY_AND_ASSIGN(Value);
+};
+
+// FundamentalValue represents the simple fundamental types of values.
+class BASE_EXPORT FundamentalValue : public Value {
+ public:
+  explicit FundamentalValue(bool in_value);
+  explicit FundamentalValue(int in_value);
+  explicit FundamentalValue(double in_value);
+  virtual ~FundamentalValue();
+
+  // Overridden from Value:
+  virtual bool GetAsBoolean(bool* out_value) const OVERRIDE;
+  virtual bool GetAsInteger(int* out_value) const OVERRIDE;
+  virtual bool GetAsDouble(double* out_value) const OVERRIDE;
+  virtual FundamentalValue* DeepCopy() const OVERRIDE;
+  virtual bool Equals(const Value* other) const OVERRIDE;
+
+ private:
+  union {
+    bool boolean_value_;
+    int integer_value_;
+    double double_value_;
+  };
+
+  DISALLOW_COPY_AND_ASSIGN(FundamentalValue);
+};
+
+class BASE_EXPORT StringValue : public Value {
+ public:
+  // Initializes a StringValue with a UTF-8 narrow character string.
+  explicit StringValue(const std::string& in_value);
+
+  // Initializes a StringValue with a string16.
+  explicit StringValue(const string16& in_value);
+
+  virtual ~StringValue();
+
+  // Overridden from Value:
+  virtual bool GetAsString(std::string* out_value) const OVERRIDE;
+  virtual bool GetAsString(string16* out_value) const OVERRIDE;
+  virtual StringValue* DeepCopy() const OVERRIDE;
+  virtual bool Equals(const Value* other) const OVERRIDE;
+
+ private:
+  std::string value_;
+
+  DISALLOW_COPY_AND_ASSIGN(StringValue);
+};
+
+class BASE_EXPORT BinaryValue: public Value {
+ public:
+  virtual ~BinaryValue();
+
+  // Creates a Value to represent a binary buffer.  The new object takes
+  // ownership of the pointer passed in, if successful.
+  // Returns NULL if buffer is NULL.
+  static BinaryValue* Create(char* buffer, size_t size);
+
+  // For situations where you want to keep ownership of your buffer, this
+  // factory method creates a new BinaryValue by copying the contents of the
+  // buffer that's passed in.
+  // Returns NULL if buffer is NULL.
+  static BinaryValue* CreateWithCopiedBuffer(const char* buffer, size_t size);
+
+  size_t GetSize() const { return size_; }
+  char* GetBuffer() { return buffer_; }
+  const char* GetBuffer() const { return buffer_; }
+
+  // Overridden from Value:
+  virtual BinaryValue* DeepCopy() const OVERRIDE;
+  virtual bool Equals(const Value* other) const OVERRIDE;
+
+ private:
+  // Constructor is private so that only objects with valid buffer pointers
+  // and size values can be created.
+  BinaryValue(char* buffer, size_t size);
+
+  char* buffer_;
+  size_t size_;
+
+  DISALLOW_COPY_AND_ASSIGN(BinaryValue);
+};
+
+// 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 BASE_EXPORT DictionaryValue : public Value {
+ public:
+  DictionaryValue();
+  virtual ~DictionaryValue();
+
+  // Returns true if the current dictionary has a value for the given key.
+  bool HasKey(const std::string& key) const;
+
+  // Returns the number of Values in this dictionary.
+  size_t size() const { return dictionary_.size(); }
+
+  // Returns whether the dictionary is empty.
+  bool empty() const { return dictionary_.empty(); }
+
+  // Clears any current contents of this dictionary.
+  void Clear();
+
+  // Sets the Value associated with the given path starting from this object.
+  // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
+  // into the next DictionaryValue down.  Obviously, "." can't be used
+  // within a key, but there are no other restrictions on keys.
+  // If the key at any step of the way doesn't exist, or exists but isn't
+  // a DictionaryValue, a new DictionaryValue will be created and attached
+  // to the path in that location.
+  // Note that the dictionary takes ownership of the value referenced by
+  // |in_value|, and therefore |in_value| must be non-NULL.
+  void Set(const std::string& path, Value* in_value);
+
+  // Convenience forms of Set().  These methods will replace any existing
+  // value at that path, even if it has a different type.
+  void SetBoolean(const std::string& path, bool in_value);
+  void SetInteger(const std::string& path, int in_value);
+  void SetDouble(const std::string& path, double in_value);
+  void SetString(const std::string& path, const std::string& in_value);
+  void SetString(const std::string& path, const string16& in_value);
+
+  // Like Set(), but without special treatment of '.'.  This allows e.g. URLs to
+  // be used as paths.
+  void SetWithoutPathExpansion(const std::string& key, Value* in_value);
+
+  // Gets the Value associated with the given path starting from this object.
+  // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
+  // into the next DictionaryValue down.  If the path can be resolved
+  // successfully, the value for the last key in the path will be returned
+  // through the |out_value| parameter, and the function will return true.
+  // Otherwise, it will return false and |out_value| will be untouched.
+  // Note that the dictionary always owns the value that's returned.
+  bool Get(const std::string& path, Value** out_value) const;
+
+  // These are convenience forms of Get().  The value will be retrieved
+  // and the return value will be true if the path is valid and the value at
+  // the end of the path can be returned in the form specified.
+  bool GetBoolean(const std::string& path, bool* out_value) const;
+  bool GetInteger(const std::string& path, int* out_value) const;
+  bool GetDouble(const std::string& path, double* out_value) const;
+  bool GetString(const std::string& path, std::string* out_value) const;
+  bool GetString(const std::string& path, string16* out_value) const;
+  bool GetStringASCII(const std::string& path, std::string* out_value) const;
+  bool GetBinary(const std::string& path, BinaryValue** out_value) const;
+  bool GetDictionary(const std::string& path,
+                     DictionaryValue** out_value) const;
+  bool GetList(const std::string& path, ListValue** out_value) const;
+
+  // Like Get(), but without special treatment of '.'.  This allows e.g. URLs to
+  // be used as paths.
+  bool GetWithoutPathExpansion(const std::string& key,
+                               Value** out_value) const;
+  bool GetIntegerWithoutPathExpansion(const std::string& key,
+                                      int* out_value) const;
+  bool GetDoubleWithoutPathExpansion(const std::string& key,
+                                   double* out_value) const;
+  bool GetStringWithoutPathExpansion(const std::string& key,
+                                     std::string* out_value) const;
+  bool GetStringWithoutPathExpansion(const std::string& key,
+                                     string16* out_value) const;
+  bool GetDictionaryWithoutPathExpansion(const std::string& key,
+                                         DictionaryValue** out_value) const;
+  bool GetListWithoutPathExpansion(const std::string& key,
+                                   ListValue** out_value) const;
+
+  // Removes the Value with the specified path from this dictionary (or one
+  // of its child dictionaries, if the path is more than just a local key).
+  // If |out_value| is non-NULL, the removed Value AND ITS OWNERSHIP will be
+  // passed out via out_value.  If |out_value| is NULL, the removed value will
+  // be deleted.  This method returns true if |path| is a valid path; otherwise
+  // it will return false and the DictionaryValue object will be unchanged.
+  bool Remove(const std::string& path, Value** out_value);
+
+  // Like Remove(), but without special treatment of '.'.  This allows e.g. URLs
+  // to be used as paths.
+  bool RemoveWithoutPathExpansion(const std::string& key, Value** out_value);
+
+  // Makes a copy of |this| but doesn't include empty dictionaries and lists in
+  // the copy.  This never returns NULL, even if |this| itself is empty.
+  DictionaryValue* DeepCopyWithoutEmptyChildren();
+
+  // Merge a given dictionary into this dictionary. This is done recursively,
+  // i.e. any subdictionaries will be merged as well. In case of key collisions,
+  // the passed in dictionary takes precedence and data already present will be
+  // replaced.
+  void MergeDictionary(const DictionaryValue* dictionary);
+
+  // Swaps contents with the |other| dictionary.
+  void Swap(DictionaryValue* other) {
+    dictionary_.swap(other->dictionary_);
+  }
+
+  // This class provides an iterator for the keys in the dictionary.
+  // It can't be used to modify the dictionary.
+  //
+  // 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
+      : private std::iterator<std::input_iterator_tag, const std::string> {
+   public:
+    explicit key_iterator(ValueMap::const_iterator itr) { itr_ = itr; }
+    key_iterator operator++() {
+      ++itr_;
+      return *this;
+    }
+    const std::string& operator*() { return itr_->first; }
+    bool operator!=(const key_iterator& other) { return itr_ != other.itr_; }
+    bool operator==(const key_iterator& other) { return itr_ == other.itr_; }
+
+   private:
+    ValueMap::const_iterator itr_;
+  };
+
+  key_iterator begin_keys() const { return key_iterator(dictionary_.begin()); }
+  key_iterator end_keys() const { return key_iterator(dictionary_.end()); }
+
+  // Overridden from Value:
+  virtual DictionaryValue* DeepCopy() const OVERRIDE;
+  virtual bool Equals(const Value* other) const OVERRIDE;
+
+ private:
+  ValueMap dictionary_;
+
+  DISALLOW_COPY_AND_ASSIGN(DictionaryValue);
+};
+
+// This type of Value represents a list of other Value values.
+class BASE_EXPORT ListValue : public Value {
+ public:
+  typedef ValueVector::iterator iterator;
+  typedef ValueVector::const_iterator const_iterator;
+
+  ListValue();
+  virtual ~ListValue();
+
+  // Clears the contents of this ListValue
+  void Clear();
+
+  // Returns the number of Values in this list.
+  size_t GetSize() const { return list_.size(); }
+
+  // Returns whether the list is empty.
+  bool empty() const { return list_.empty(); }
+
+  // Sets the list item at the given index to be the Value specified by
+  // the value given.  If the index beyond the current end of the list, null
+  // Values will be used to pad out the list.
+  // Returns true if successful, or false if the index was negative or
+  // the value is a null pointer.
+  bool Set(size_t index, Value* in_value);
+
+  // Gets the Value at the given index.  Modifies |out_value| (and returns true)
+  // only if the index falls within the current list range.
+  // Note that the list always owns the Value passed out via |out_value|.
+  bool Get(size_t index, Value** out_value) const;
+
+  // Convenience forms of Get().  Modifies |out_value| (and returns true)
+  // only if the index is valid and the Value at that index can be returned
+  // in the specified form.
+  bool GetBoolean(size_t index, bool* out_value) const;
+  bool GetInteger(size_t index, int* out_value) const;
+  bool GetDouble(size_t index, double* out_value) const;
+  bool GetString(size_t index, std::string* out_value) const;
+  bool GetString(size_t index, string16* out_value) const;
+  bool GetBinary(size_t index, BinaryValue** out_value) const;
+  bool GetDictionary(size_t index, DictionaryValue** out_value) const;
+  bool GetList(size_t index, ListValue** out_value) const;
+
+  // Removes the Value with the specified index from this list.
+  // If |out_value| is non-NULL, the removed Value AND ITS OWNERSHIP will be
+  // passed out via |out_value|.  If |out_value| is NULL, the removed value will
+  // be deleted.  This method returns true if |index| is valid; otherwise
+  // it will return false and the ListValue object will be unchanged.
+  bool Remove(size_t index, Value** out_value);
+
+  // Removes the first instance of |value| found in the list, if any, and
+  // deletes it. |index| is the location where |value| was found. Returns false
+  // if not found.
+  bool Remove(const Value& value, size_t* index);
+
+  // Appends a Value to the end of the list.
+  void Append(Value* in_value);
+
+  // 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.
+  // Returns true if successful, or false if the index was out of range.
+  bool Insert(size_t index, Value* in_value);
+
+  // Swaps contents with the |other| list.
+  void Swap(ListValue* other) {
+    list_.swap(other->list_);
+  }
+
+  // Iteration.
+  iterator begin() { return list_.begin(); }
+  iterator end() { return list_.end(); }
+
+  const_iterator begin() const { return list_.begin(); }
+  const_iterator end() const { return list_.end(); }
+
+  // Overridden from Value:
+  virtual bool GetAsList(ListValue** out_value) OVERRIDE;
+  virtual bool GetAsList(const ListValue** out_value) const OVERRIDE;
+  virtual ListValue* DeepCopy() const OVERRIDE;
+  virtual bool Equals(const Value* other) const OVERRIDE;
+
+ private:
+  ValueVector list_;
+
+  DISALLOW_COPY_AND_ASSIGN(ListValue);
+};
+
+// This interface is implemented by classes that know how to serialize and
+// deserialize Value objects.
+class BASE_EXPORT ValueSerializer {
+ public:
+  virtual ~ValueSerializer();
+
+  virtual bool Serialize(const Value& root) = 0;
+
+  // This method deserializes the subclass-specific format into a Value object.
+  // If the return value is non-NULL, the caller takes ownership of returned
+  // Value. If the return value is NULL, and if error_code is non-NULL,
+  // error_code will be set with the underlying error.
+  // If |error_message| is non-null, it will be filled in with a formatted
+  // error message including the location of the error if appropriate.
+  virtual Value* Deserialize(int* error_code, std::string* error_str) = 0;
+};
+
+}  // namespace base
+
+// http://crbug.com/88666
+using base::DictionaryValue;
+using base::ListValue;
+using base::StringValue;
+using base::Value;
+
+#endif  // BASE_VALUES_H_
diff --git a/build/build_config.h b/build/build_config.h
new file mode 100644 (file)
index 0000000..ce5ac6a
--- /dev/null
@@ -0,0 +1,151 @@
+// 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 adds defines about the platform we're currently building on.
+//  Operating System:
+//    OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX)
+//  Compiler:
+//    COMPILER_MSVC / COMPILER_GCC
+//  Processor:
+//    ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64)
+//    ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
+
+#ifndef BUILD_BUILD_CONFIG_H_
+#define BUILD_BUILD_CONFIG_H_
+
+// A set of macros to use for platform detection.
+#if defined(__APPLE__)
+#define OS_MACOSX 1
+#elif defined(ANDROID)
+#define OS_ANDROID 1
+#elif defined(__native_client__)
+#define OS_NACL 1
+#elif defined(__linux__)
+#define OS_LINUX 1
+// Use TOOLKIT_GTK on linux if TOOLKIT_VIEWS isn't defined.
+#if !defined(TOOLKIT_VIEWS)
+#define TOOLKIT_GTK
+#endif
+#elif defined(_WIN32)
+#define OS_WIN 1
+#define TOOLKIT_VIEWS 1
+#elif defined(__FreeBSD__)
+#define OS_FREEBSD 1
+#define TOOLKIT_GTK
+#elif defined(__OpenBSD__)
+#define OS_OPENBSD 1
+#define TOOLKIT_GTK
+#elif defined(__sun)
+#define OS_SOLARIS 1
+#define TOOLKIT_GTK
+#else
+#error Please add support for your platform in build/build_config.h
+#endif
+
+// A flag derived from the above flags, used to cover GTK code in
+// both TOOLKIT_GTK and TOOLKIT_VIEWS.
+#if defined(TOOLKIT_GTK) || (defined(TOOLKIT_VIEWS) && !defined(OS_WIN))
+#define TOOLKIT_USES_GTK 1
+#endif
+
+#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || \
+    defined(OS_SOLARIS) || defined(OS_ANDROID)
+#if !defined(USE_OPENSSL)
+#define USE_NSS 1  // Default to use NSS for crypto, unless OpenSSL is chosen.
+#endif
+#ifndef OS_ANDROID
+#define USE_X11 1  // Use X for graphics.
+#endif
+#endif
+
+#if defined(USE_OPENSSL) && defined(USE_NSS)
+#error Cannot use both OpenSSL and NSS
+#endif
+
+// For access to standard POSIXish features, use OS_POSIX instead of a
+// more specific macro.
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) ||     \
+    defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_ANDROID) ||  \
+    defined(OS_NACL)
+#define OS_POSIX 1
+#endif
+
+// Use tcmalloc
+#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(NO_TCMALLOC)
+#define USE_TCMALLOC 1
+#endif
+
+// Use heapchecker.
+#if defined(OS_LINUX) && !defined(NO_HEAPCHECKER)
+#define USE_HEAPCHECKER 1
+#endif
+
+// Compiler detection.
+#if defined(__GNUC__)
+#define COMPILER_GCC 1
+#elif defined(_MSC_VER)
+#define COMPILER_MSVC 1
+#else
+#error Please add support for your compiler in build/build_config.h
+#endif
+
+// Processor architecture detection.  For more info on what's defined, see:
+//   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+//   http://www.agner.org/optimize/calling_conventions.pdf
+//   or with gcc, run: "echo | gcc -E -dM -"
+#if defined(_M_X64) || defined(__x86_64__)
+#define ARCH_CPU_X86_FAMILY 1
+#define ARCH_CPU_X86_64 1
+#define ARCH_CPU_64_BITS 1
+#define ARCH_CPU_LITTLE_ENDIAN 1
+#elif defined(_M_IX86) || defined(__i386__)
+#define ARCH_CPU_X86_FAMILY 1
+#define ARCH_CPU_X86 1
+#define ARCH_CPU_32_BITS 1
+#define ARCH_CPU_LITTLE_ENDIAN 1
+#elif defined(__ARMEL__)
+#define ARCH_CPU_ARM_FAMILY 1
+#define ARCH_CPU_ARMEL 1
+#define ARCH_CPU_32_BITS 1
+#define ARCH_CPU_LITTLE_ENDIAN 1
+#define WCHAR_T_IS_UNSIGNED 1
+#else
+#error Please add support for your architecture in build/build_config.h
+#endif
+
+// Type detection for wchar_t.
+#if defined(OS_WIN)
+#define WCHAR_T_IS_UTF16
+#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
+    defined(__WCHAR_MAX__) && \
+    (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define WCHAR_T_IS_UTF32
+#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
+    defined(__WCHAR_MAX__) && \
+    (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to
+// compile in this mode (in particular, Chrome doesn't). This is intended for
+// other projects using base who manage their own dependencies and make sure
+// short wchar works for them.
+#define WCHAR_T_IS_UTF16
+#else
+#error Please add support for your compiler in build/build_config.h
+#endif
+
+#if defined(OS_CHROMEOS)
+// Single define to trigger whether CrOS fonts have BCI on.
+// In that case font sizes/deltas should be adjusted.
+//define CROS_FONTS_USING_BCI
+#endif
+
+#if defined(OS_ANDROID)
+// The compiler thinks std::string::const_iterator and "const char*" are
+// equivalent types.
+#define STD_STRING_ITERATOR_IS_CHAR_POINTER
+// The compiler thinks base::string16::const_iterator and "char16*" are
+// equivalent types.
+#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER
+#endif
+
+#endif  // BUILD_BUILD_CONFIG_H_
diff --git a/chromium.manifest b/chromium.manifest
new file mode 100644 (file)
index 0000000..ae3e6f7
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
\ No newline at end of file
diff --git a/chromium.pc.in b/chromium.pc.in
new file mode 100755 (executable)
index 0000000..b6609e0
--- /dev/null
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=/usr/lib
+includedir=/usr/include/chromium
+
+Name: @PC_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @VERSION@
+Requires: @PC_REQUIRED@ 
+Libs: -L${libdir} @PC_LDFLAGS@
+Cflags: -I${includedir}
+
diff --git a/ipc/OWNERS b/ipc/OWNERS
new file mode 100644 (file)
index 0000000..fc187f8
--- /dev/null
@@ -0,0 +1,7 @@
+agl@chromium.org
+cpu@chromium.org
+darin@chromium.org
+dmaclach@chromium.org
+jam@chromium.org
+jeremy@chromium.org
+tsepez@chromium.org
diff --git a/ipc/file_descriptor_set_posix.cc b/ipc/file_descriptor_set_posix.cc
new file mode 100644 (file)
index 0000000..7f17322
--- /dev/null
@@ -0,0 +1,136 @@
+// 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 "ipc/file_descriptor_set_posix.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/logging.h"
+
+FileDescriptorSet::FileDescriptorSet()
+    : consumed_descriptor_highwater_(0) {
+}
+
+FileDescriptorSet::~FileDescriptorSet() {
+  if (consumed_descriptor_highwater_ == descriptors_.size())
+    return;
+
+  LOG(WARNING) << "FileDescriptorSet destroyed with unconsumed descriptors";
+  // We close all the descriptors where the close flag is set. If this
+  // message should have been transmitted, then closing those with close
+  // flags set mirrors the expected behaviour.
+  //
+  // If this message was received with more descriptors than expected
+  // (which could a DOS against the browser by a rogue renderer) then all
+  // the descriptors have their close flag set and we free all the extra
+  // kernel resources.
+  for (unsigned i = consumed_descriptor_highwater_;
+       i < descriptors_.size(); ++i) {
+    if (descriptors_[i].auto_close)
+      if (HANDLE_EINTR(close(descriptors_[i].fd)) < 0)
+        PLOG(ERROR) << "close";
+  }
+}
+
+bool FileDescriptorSet::Add(int fd) {
+  if (descriptors_.size() == MAX_DESCRIPTORS_PER_MESSAGE)
+    return false;
+
+  struct base::FileDescriptor sd;
+  sd.fd = fd;
+  sd.auto_close = false;
+  descriptors_.push_back(sd);
+  return true;
+}
+
+bool FileDescriptorSet::AddAndAutoClose(int fd) {
+  if (descriptors_.size() == MAX_DESCRIPTORS_PER_MESSAGE)
+    return false;
+
+  struct base::FileDescriptor sd;
+  sd.fd = fd;
+  sd.auto_close = true;
+  descriptors_.push_back(sd);
+  DCHECK(descriptors_.size() <= MAX_DESCRIPTORS_PER_MESSAGE);
+  return true;
+}
+
+int FileDescriptorSet::GetDescriptorAt(unsigned index) const {
+  if (index >= descriptors_.size())
+    return -1;
+
+  // We should always walk the descriptors in order, so it's reasonable to
+  // enforce this. Consider the case where a compromised renderer sends us
+  // the following message:
+  //
+  //   ExampleMsg:
+  //     num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
+  //
+  // Here the renderer sent us a message which should have a descriptor, but
+  // actually sent two in an attempt to fill our fd table and kill us. By
+  // setting the index of the descriptor in the message to 1 (it should be
+  // 0), we would record a highwater of 1 and then consider all the
+  // descriptors to have been used.
+  //
+  // So we can either track of the use of each descriptor in a bitset, or we
+  // can enforce that we walk the indexes strictly in order.
+  //
+  // There's one more wrinkle: When logging messages, we may reparse them. So
+  // we have an exception: When the consumed_descriptor_highwater_ is at the
+  // end of the array and index 0 is requested, we reset the highwater value.
+  if (index == 0 && consumed_descriptor_highwater_ == descriptors_.size())
+    consumed_descriptor_highwater_ = 0;
+
+  if (index != consumed_descriptor_highwater_)
+    return -1;
+
+  consumed_descriptor_highwater_ = index + 1;
+  return descriptors_[index].fd;
+}
+
+void FileDescriptorSet::GetDescriptors(int* buffer) const {
+  for (std::vector<base::FileDescriptor>::const_iterator
+       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
+    *(buffer++) = i->fd;
+  }
+}
+
+bool FileDescriptorSet::ContainsDirectoryDescriptor() const {
+  struct stat st;
+
+  for (std::vector<base::FileDescriptor>::const_iterator
+       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
+    if (fstat(i->fd, &st) == 0 && S_ISDIR(st.st_mode))
+      return true;
+  }
+
+  return false;
+}
+
+void FileDescriptorSet::CommitAll() {
+  for (std::vector<base::FileDescriptor>::iterator
+       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
+    if (i->auto_close)
+      if (HANDLE_EINTR(close(i->fd)) < 0)
+        PLOG(ERROR) << "close";
+  }
+  descriptors_.clear();
+  consumed_descriptor_highwater_ = 0;
+}
+
+void FileDescriptorSet::SetDescriptors(const int* buffer, unsigned count) {
+  DCHECK_LE(count, MAX_DESCRIPTORS_PER_MESSAGE);
+  DCHECK_EQ(descriptors_.size(), 0u);
+  DCHECK_EQ(consumed_descriptor_highwater_, 0u);
+
+  descriptors_.reserve(count);
+  for (unsigned i = 0; i < count; ++i) {
+    struct base::FileDescriptor sd;
+    sd.fd = buffer[i];
+    sd.auto_close = true;
+    descriptors_.push_back(sd);
+  }
+}
diff --git a/ipc/file_descriptor_set_posix.h b/ipc/file_descriptor_set_posix.h
new file mode 100644 (file)
index 0000000..1554c38
--- /dev/null
@@ -0,0 +1,117 @@
+// 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 IPC_FILE_DESCRIPTOR_SET_POSIX_H_
+#define IPC_FILE_DESCRIPTOR_SET_POSIX_H_
+#pragma once
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_descriptor_posix.h"
+#include "base/memory/ref_counted.h"
+#include "ipc/ipc_export.h"
+
+// -----------------------------------------------------------------------------
+// A FileDescriptorSet is an ordered set of POSIX file descriptors. These are
+// associated with IPC messages so that descriptors can be transmitted over a
+// UNIX domain socket.
+// -----------------------------------------------------------------------------
+class IPC_EXPORT FileDescriptorSet
+    : public base::RefCountedThreadSafe<FileDescriptorSet> {
+ public:
+  FileDescriptorSet();
+
+  // This is the maximum number of descriptors per message. We need to know this
+  // because the control message kernel interface has to be given a buffer which
+  // is large enough to store all the descriptor numbers. Otherwise the kernel
+  // tells us that it truncated the control data and the extra descriptors are
+  // lost.
+  //
+  // In debugging mode, it's a fatal error to try and add more than this number
+  // of descriptors to a FileDescriptorSet.
+  enum {
+    MAX_DESCRIPTORS_PER_MESSAGE = 5,
+  };
+
+  // ---------------------------------------------------------------------------
+  // Interfaces for building during message serialisation...
+
+  // Add a descriptor to the end of the set. Returns false iff the set is full.
+  bool Add(int fd);
+  // Add a descriptor to the end of the set and automatically close it after
+  // transmission. Returns false iff the set is full.
+  bool AddAndAutoClose(int fd);
+
+  // ---------------------------------------------------------------------------
+
+
+  // ---------------------------------------------------------------------------
+  // Interfaces for accessing during message deserialisation...
+
+  // Return the number of descriptors
+  unsigned size() const { return descriptors_.size(); }
+  // Return true if no unconsumed descriptors remain
+  bool empty() const { return descriptors_.empty(); }
+  // Fetch the nth descriptor from the beginning of the set. Code using this
+  // /must/ access the descriptors in order, except that it may wrap from the
+  // end to index 0 again.
+  //
+  // This interface is designed for the deserialising code as it doesn't
+  // support close flags.
+  //   returns: file descriptor, or -1 on error
+  int GetDescriptorAt(unsigned n) const;
+
+  // ---------------------------------------------------------------------------
+
+
+  // ---------------------------------------------------------------------------
+  // Interfaces for transmission...
+
+  // Fill an array with file descriptors without 'consuming' them. CommitAll
+  // must be called after these descriptors have been transmitted.
+  //   buffer: (output) a buffer of, at least, size() integers.
+  void GetDescriptors(int* buffer) const;
+  // This must be called after transmitting the descriptors returned by
+  // GetDescriptors. It marks all the descriptors as consumed and closes those
+  // which are auto-close.
+  void CommitAll();
+  // Returns true if any contained file descriptors appear to be handles to a
+  // directory.
+  bool ContainsDirectoryDescriptor() const;
+
+  // ---------------------------------------------------------------------------
+
+
+  // ---------------------------------------------------------------------------
+  // Interfaces for receiving...
+
+  // Set the contents of the set from the given buffer. This set must be empty
+  // before calling. The auto-close flag is set on all the descriptors so that
+  // unconsumed descriptors are closed on destruction.
+  void SetDescriptors(const int* buffer, unsigned count);
+
+  // ---------------------------------------------------------------------------
+
+ private:
+  friend class base::RefCountedThreadSafe<FileDescriptorSet>;
+
+  ~FileDescriptorSet();
+
+  // A vector of descriptors and close flags. If this message is sent, then
+  // these descriptors are sent as control data. After sending, any descriptors
+  // with a true flag are closed. If this message has been received, then these
+  // are the descriptors which were received and all close flags are true.
+  std::vector<base::FileDescriptor> descriptors_;
+
+  // This contains the index of the next descriptor which should be consumed.
+  // It's used in a couple of ways. Firstly, at destruction we can check that
+  // all the descriptors have been read (with GetNthDescriptor). Secondly, we
+  // can check that they are read in order.
+  mutable unsigned consumed_descriptor_highwater_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileDescriptorSet);
+};
+
+#endif  // IPC_FILE_DESCRIPTOR_SET_POSIX_H_
diff --git a/ipc/file_descriptor_set_posix_unittest.cc b/ipc/file_descriptor_set_posix_unittest.cc
new file mode 100644 (file)
index 0000000..5fc8c50
--- /dev/null
@@ -0,0 +1,179 @@
+// Copyright (c) 2006-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.
+
+// This test is POSIX only.
+
+#include "ipc/file_descriptor_set_posix.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "base/basictypes.h"
+#include "base/eintr_wrapper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Get a safe file descriptor for test purposes.
+int GetSafeFd() {
+  return open("/dev/null", O_RDONLY);
+}
+
+// Returns true if fd was already closed.  Closes fd if not closed.
+bool VerifyClosed(int fd) {
+  const int duped = dup(fd);
+  if (duped != -1) {
+    EXPECT_NE(HANDLE_EINTR(close(duped)), -1);
+    EXPECT_NE(HANDLE_EINTR(close(fd)), -1);
+    return false;
+  }
+  return true;
+}
+
+// The FileDescriptorSet will try and close some of the descriptor numbers
+// which we given it. This is the base descriptor value. It's great enough such
+// that no real descriptor will accidently be closed.
+static const int kFDBase = 50000;
+
+TEST(FileDescriptorSet, BasicAdd) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  ASSERT_EQ(set->size(), 0u);
+  ASSERT_TRUE(set->empty());
+  ASSERT_TRUE(set->Add(kFDBase));
+  ASSERT_EQ(set->size(), 1u);
+  ASSERT_TRUE(!set->empty());
+
+  // Empties the set and stops a warning about deleting a set with unconsumed
+  // descriptors
+  set->CommitAll();
+}
+
+TEST(FileDescriptorSet, BasicAddAndClose) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  ASSERT_EQ(set->size(), 0u);
+  ASSERT_TRUE(set->empty());
+  const int fd = GetSafeFd();
+  ASSERT_TRUE(set->AddAndAutoClose(fd));
+  ASSERT_EQ(set->size(), 1u);
+  ASSERT_TRUE(!set->empty());
+
+  set->CommitAll();
+
+  ASSERT_TRUE(VerifyClosed(fd));
+}
+TEST(FileDescriptorSet, MaxSize) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  for (unsigned i = 0;
+       i < FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE; ++i) {
+    ASSERT_TRUE(set->Add(kFDBase + 1 + i));
+  }
+
+  ASSERT_TRUE(!set->Add(kFDBase));
+
+  set->CommitAll();
+}
+
+TEST(FileDescriptorSet, SetDescriptors) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  ASSERT_TRUE(set->empty());
+  set->SetDescriptors(NULL, 0);
+  ASSERT_TRUE(set->empty());
+
+  const int fd = GetSafeFd();
+  static const int fds[] = {fd};
+  set->SetDescriptors(fds, 1);
+  ASSERT_TRUE(!set->empty());
+  ASSERT_EQ(set->size(), 1u);
+
+  set->CommitAll();
+
+  ASSERT_TRUE(VerifyClosed(fd));
+}
+
+TEST(FileDescriptorSet, GetDescriptors) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  set->GetDescriptors(NULL);
+  ASSERT_TRUE(set->Add(kFDBase));
+
+  int fds[1];
+  fds[0] = 0;
+  set->GetDescriptors(fds);
+  ASSERT_EQ(fds[0], kFDBase);
+  set->CommitAll();
+  ASSERT_TRUE(set->empty());
+}
+
+TEST(FileDescriptorSet, WalkInOrder) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  ASSERT_TRUE(set->Add(kFDBase));
+  ASSERT_TRUE(set->Add(kFDBase + 1));
+  ASSERT_TRUE(set->Add(kFDBase + 2));
+
+  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
+  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
+  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
+
+  set->CommitAll();
+}
+
+TEST(FileDescriptorSet, WalkWrongOrder) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  ASSERT_TRUE(set->Add(kFDBase));
+  ASSERT_TRUE(set->Add(kFDBase + 1));
+  ASSERT_TRUE(set->Add(kFDBase + 2));
+
+  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
+  ASSERT_EQ(set->GetDescriptorAt(2), -1);
+
+  set->CommitAll();
+}
+
+TEST(FileDescriptorSet, WalkCycle) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  ASSERT_TRUE(set->Add(kFDBase));
+  ASSERT_TRUE(set->Add(kFDBase + 1));
+  ASSERT_TRUE(set->Add(kFDBase + 2));
+
+  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
+  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
+  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
+  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
+  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
+  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
+  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
+  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
+  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
+
+  set->CommitAll();
+}
+
+TEST(FileDescriptorSet, DontClose) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  const int fd = GetSafeFd();
+  ASSERT_TRUE(set->Add(fd));
+  set->CommitAll();
+
+  ASSERT_FALSE(VerifyClosed(fd));
+}
+
+TEST(FileDescriptorSet, DoClose) {
+  scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
+
+  const int fd = GetSafeFd();
+  ASSERT_TRUE(set->AddAndAutoClose(fd));
+  set->CommitAll();
+
+  ASSERT_TRUE(VerifyClosed(fd));
+}
+
+}  // namespace
diff --git a/ipc/ipc.gyp b/ipc/ipc.gyp
new file mode 100644 (file)
index 0000000..ab57cd9
--- /dev/null
@@ -0,0 +1,90 @@
+# 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.
+
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'target_defaults': {
+    'sources/': [
+      ['exclude', '/win/'],
+      ['exclude', '_(posix|win)(_unittest)?\\.(cc|mm?)$'],
+      ['exclude', '/win_[^/]*\\.cc$'],
+    ],
+    'conditions': [
+      ['os_posix == 1 and OS != "mac"', {'sources/': [
+        ['include', '_posix(_unittest)?\\.cc$'],
+      ]}],
+      ['OS=="mac"', {'sources/': [
+        ['include', '_posix(_unittest)?\\.(cc|mm?)$'],
+      ]}],
+      ['OS=="win"', {'sources/': [
+        ['include', '_win(_unittest)?\\.cc$'],
+        ['include', '/win/'],
+        ['include', '/win_[^/]*\\.cc$'],
+      ]}],
+    ],
+  },
+  'includes': [
+    'ipc.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'ipc_tests',
+      'type': 'executable',
+      'dependencies': [
+        'ipc',
+        '../base/base.gyp:base',
+        '../base/base.gyp:base_i18n',
+        '../base/base.gyp:test_support_base',
+        '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../testing/gtest.gyp:gtest',
+      ],
+      'include_dirs': [
+        '..'
+      ],
+      'sources': [
+        'file_descriptor_set_posix_unittest.cc',
+        'ipc_channel_posix_unittest.cc',
+        'ipc_fuzzing_tests.cc',
+        'ipc_message_unittest.cc',
+        'ipc_send_fds_test.cc',
+        'ipc_sync_channel_unittest.cc',
+        'ipc_sync_message_unittest.cc',
+        'ipc_sync_message_unittest.h',
+        'ipc_tests.cc',
+        'ipc_tests.h',
+        'sync_socket_unittest.cc',
+      ],
+      'conditions': [
+        ['toolkit_uses_gtk == 1', {
+          'dependencies': [
+            '../build/linux/system.gyp:gtk',
+          ],
+        }],
+        ['os_posix == 1 and OS != "mac"', {
+          'conditions': [
+            ['linux_use_tcmalloc==1', {
+              'dependencies': [
+                '../base/allocator/allocator.gyp:allocator',
+              ],
+            }],
+          ],
+        }]
+      ],
+    },
+    {
+      'target_name': 'test_support_ipc',
+      'type': 'static_library',
+      'dependencies': [
+        'ipc',
+        '../base/base.gyp:base',
+      ],
+      'sources': [
+        'ipc_test_sink.cc',
+        'ipc_test_sink.h',
+      ],
+    },
+  ],
+}
diff --git a/ipc/ipc.gypi b/ipc/ipc.gypi
new file mode 100644 (file)
index 0000000..7791934
--- /dev/null
@@ -0,0 +1,109 @@
+# 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.
+
+{
+  'target_defaults': {
+    'variables': {
+      'ipc_target': 0,
+    },
+    'target_conditions': [
+      # This part is shared between the targets defined below.
+      ['ipc_target==1', {
+        'sources': [
+          'file_descriptor_set_posix.cc',
+          'file_descriptor_set_posix.h',
+          'ipc_channel.h',
+          'ipc_channel_handle.h',
+          'ipc_channel_posix.cc',
+          'ipc_channel_posix.h',
+          'ipc_channel_proxy.cc',
+          'ipc_channel_proxy.h',
+          'ipc_channel_win.cc',
+          'ipc_channel_win.h',
+          'ipc_descriptors.h',
+          'ipc_export.h',
+          'ipc_logging.cc',
+          'ipc_logging.h',
+          'ipc_message.cc',
+          'ipc_message.h',
+          'ipc_message_macros.h',
+          'ipc_message_utils.cc',
+          'ipc_message_utils.h',
+          'ipc_param_traits.h',
+          'ipc_platform_file.cc',
+          'ipc_platform_file.h',
+          'ipc_switches.cc',
+          'ipc_switches.h',
+          'ipc_sync_channel.cc',
+          'ipc_sync_channel.h',
+          'ipc_sync_message.cc',
+          'ipc_sync_message.h',
+          'ipc_sync_message_filter.cc',
+          'ipc_sync_message_filter.h',
+          'param_traits_log_macros.h',
+          'param_traits_macros.h',
+          'param_traits_read_macros.h',
+          'param_traits_write_macros.h',
+          'struct_constructor_macros.h',
+          'struct_destructor_macros.h',
+        ],
+        'defines': [
+          'IPC_IMPLEMENTATION',
+        ],
+        'include_dirs': [
+          '..',
+        ],
+      }],
+    ],
+  },
+  'targets': [
+    {
+      'target_name': 'ipc',
+      'type': '<(component)',
+      'variables': {
+        'ipc_target': 1,
+      },
+      'dependencies': [
+        '../base/base.gyp:base',
+        '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+      ],
+      # TODO(gregoryd): direct_dependent_settings should be shared with the
+      # 64-bit target, but it doesn't work due to a bug in gyp
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '..',
+        ],
+      },
+    },
+  ],
+  'conditions': [
+    ['OS=="win"', {
+      'targets': [
+        {
+          'target_name': 'ipc_win64',
+          'type': '<(component)',
+          'variables': {
+            'ipc_target': 1,
+          },
+          'dependencies': [
+            '../base/base.gyp:base_nacl_win64',
+            '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
+          ],
+          # TODO(gregoryd): direct_dependent_settings should be shared with the
+          # 32-bit target, but it doesn't work due to a bug in gyp
+          'direct_dependent_settings': {
+            'include_dirs': [
+              '..',
+            ],
+          },
+          'configurations': {
+            'Common_Base': {
+              'msvs_target_platform': 'x64',
+            },
+          },
+        },
+      ],
+    }],
+  ],
+}
diff --git a/ipc/ipc_channel.h b/ipc/ipc_channel.h
new file mode 100644 (file)
index 0000000..cd57b4b
--- /dev/null
@@ -0,0 +1,204 @@
+// 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 IPC_IPC_CHANNEL_H_
+#define IPC_IPC_CHANNEL_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message.h"
+
+namespace IPC {
+
+//------------------------------------------------------------------------------
+// See
+// http://www.chromium.org/developers/design-documents/inter-process-communication
+// for overview of IPC in Chromium.
+
+// Channels are implemented using named pipes on Windows, and
+// socket pairs (or in some special cases unix domain sockets) on POSIX.
+// On Windows we access pipes in various processes by name.
+// On POSIX we pass file descriptors to child processes and assign names to them
+// in a lookup table.
+// In general on POSIX we do not use unix domain sockets due to security
+// concerns and the fact that they can leave garbage around the file system
+// (MacOS does not support abstract named unix domain sockets).
+// You can use unix domain sockets if you like on POSIX by constructing the
+// the channel with the mode set to one of the NAMED modes. NAMED modes are
+// currently used by automation and service processes.
+
+class IPC_EXPORT Channel : public Message::Sender {
+  // Security tests need access to the pipe handle.
+  friend class ChannelTest;
+
+ public:
+  // Implemented by consumers of a Channel to receive messages.
+  class IPC_EXPORT Listener {
+   public:
+    virtual ~Listener() {}
+
+    // Called when a message is received.  Returns true iff the message was
+    // handled.
+    virtual bool OnMessageReceived(const Message& message) = 0;
+
+    // Called when the channel is connected and we have received the internal
+    // Hello message from the peer.
+    virtual void OnChannelConnected(int32 peer_pid) {}
+
+    // Called when an error is detected that causes the channel to close.
+    // This method is not called when a channel is closed normally.
+    virtual void OnChannelError() {}
+
+#if defined(OS_POSIX)
+    // Called on the server side when a channel that listens for connections
+    // denies an attempt to connect.
+    virtual void OnChannelDenied() {}
+
+    // Called on the server side when a channel that listens for connections
+    // has an error that causes the listening channel to close.
+    virtual void OnChannelListenError() {}
+#endif  // OS_POSIX
+  };
+
+  // Flags to test modes
+  enum ModeFlags {
+    MODE_NO_FLAG = 0x0,
+    MODE_SERVER_FLAG = 0x1,
+    MODE_CLIENT_FLAG = 0x2,
+    MODE_NAMED_FLAG = 0x4,
+#if defined(OS_POSIX)
+    MODE_OPEN_ACCESS_FLAG = 0x8, // Don't restrict access based on client UID.
+#endif
+  };
+
+  // Some Standard Modes
+  enum Mode {
+    MODE_NONE = MODE_NO_FLAG,
+    MODE_SERVER = MODE_SERVER_FLAG,
+    MODE_CLIENT = MODE_CLIENT_FLAG,
+    // Channels on Windows are named by default and accessible from other
+    // processes. On POSIX channels are anonymous by default and not accessible
+    // from other processes. Named channels work via named unix domain sockets.
+    // On Windows MODE_NAMED_SERVER is equivalent to MODE_SERVER and
+    // MODE_NAMED_CLIENT is equivalent to MODE_CLIENT.
+    MODE_NAMED_SERVER = MODE_SERVER_FLAG | MODE_NAMED_FLAG,
+    MODE_NAMED_CLIENT = MODE_CLIENT_FLAG | MODE_NAMED_FLAG,
+#if defined(OS_POSIX)
+    // An "open" named server accepts connections from ANY client.
+    // The caller must then implement their own access-control based on the
+    // client process' user Id.
+    MODE_OPEN_NAMED_SERVER = MODE_OPEN_ACCESS_FLAG | MODE_SERVER_FLAG |
+                             MODE_NAMED_FLAG
+#endif
+  };
+
+  enum {
+    // The maximum message size in bytes. Attempting to receive a
+    // message of this size or bigger results in a channel error.
+    kMaximumMessageSize = 128 * 1024 * 1024,
+
+    // Ammount of data to read at once from the pipe.
+    kReadBufferSize = 4 * 1024
+  };
+
+  // Initialize a Channel.
+  //
+  // |channel_handle| identifies the communication Channel. For POSIX, if
+  // the file descriptor in the channel handle is != -1, the channel takes
+  // ownership of the file descriptor and will close it appropriately, otherwise
+  // it will create a new descriptor internally.
+  // |mode| specifies whether this Channel is to operate in server mode or
+  // client mode.  In server mode, the Channel is responsible for setting up the
+  // IPC object, whereas in client mode, the Channel merely connects to the
+  // already established IPC object.
+  // |listener| receives a callback on the current thread for each newly
+  // received message.
+  //
+  Channel(const IPC::ChannelHandle &channel_handle, Mode mode,
+          Listener* listener);
+
+  virtual ~Channel();
+
+  // Connect the pipe.  On the server side, this will initiate
+  // waiting for connections.  On the client, it attempts to
+  // connect to a pre-existing pipe.  Note, calling Connect()
+  // will not block the calling thread and may complete
+  // asynchronously.
+  bool Connect() WARN_UNUSED_RESULT;
+
+  // Close this Channel explicitly.  May be called multiple times.
+  // On POSIX calling close on an IPC channel that listens for connections will
+  // cause it to close any accepted connections, and it will stop listening for
+  // new connections. If you just want to close the currently accepted
+  // connection and listen for new ones, use ResetToAcceptingConnectionState.
+  void Close();
+
+  // Modify the Channel's listener.
+  void set_listener(Listener* listener);
+
+  // Send a message over the Channel to the listener on the other end.
+  //
+  // |message| must be allocated using operator new.  This object will be
+  // deleted once the contents of the Message have been sent.
+  virtual bool Send(Message* message);
+
+#if defined(OS_POSIX) && !defined(OS_NACL)
+  // On POSIX an IPC::Channel wraps a socketpair(), this method returns the
+  // FD # for the client end of the socket.
+  // This method may only be called on the server side of a channel.
+  int GetClientFileDescriptor() const;
+
+  // On POSIX an IPC::Channel can either wrap an established socket, or it
+  // can wrap a socket that is listening for connections. Currently an
+  // IPC::Channel that listens for connections can only accept one connection
+  // at a time.
+
+  // Returns true if the channel supports listening for connections.
+  bool AcceptsConnections() const;
+
+  // Returns true if the channel supports listening for connections and is
+  // currently connected.
+  bool HasAcceptedConnection() const;
+
+  // Returns true if the peer process' effective user id can be determined, in
+  // which case the supplied client_euid is updated with it.
+  bool GetClientEuid(uid_t* client_euid) const;
+
+  // Closes any currently connected socket, and returns to a listening state
+  // for more connections.
+  void ResetToAcceptingConnectionState();
+#endif  // defined(OS_POSIX) && !defined(OS_NACL)
+
+  // Returns true if a named server channel is initialized on the given channel
+  // ID. Even if true, the server may have already accepted a connection.
+  static bool IsNamedServerInitialized(const std::string& channel_id);
+
+ protected:
+  // Used in Chrome by the TestSink to provide a dummy channel implementation
+  // for testing. TestSink overrides the "interesting" functions in Channel so
+  // no actual implementation is needed. This will cause un-overridden calls to
+  // segfault. Do not use outside of test code!
+  Channel() : channel_impl_(0) { }
+
+ private:
+  // PIMPL to which all channel calls are delegated.
+  class ChannelImpl;
+  ChannelImpl *channel_impl_;
+
+  // The Hello message is internal to the Channel class.  It is sent
+  // by the peer when the channel is connected.  The message contains
+  // just the process id (pid).  The message has a special routing_id
+  // (MSG_ROUTING_NONE) and type (HELLO_MESSAGE_TYPE).
+  enum {
+    HELLO_MESSAGE_TYPE = kuint16max  // Maximum value of message type (uint16),
+                                     // to avoid conflicting with normal
+                                     // message types, which are enumeration
+                                     // constants starting from 0.
+  };
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_CHANNEL_H_
diff --git a/ipc/ipc_channel_handle.h b/ipc/ipc_channel_handle.h
new file mode 100644 (file)
index 0000000..ba034cc
--- /dev/null
@@ -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.
+
+#ifndef IPC_IPC_CHANNEL_HANDLE_H_
+#define IPC_IPC_CHANNEL_HANDLE_H_
+#pragma once
+
+#include <string>
+
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#endif
+
+// On Windows, any process can create an IPC channel and others can fetch
+// it by name.  We pass around the channel names over IPC.
+// On POSIX, we instead pass around handles to channel endpoints via IPC.
+// When it's time to IPC a new channel endpoint around, we send both the
+// channel name as well as a base::FileDescriptor, which is itself a special
+// type that knows how to copy a socket endpoint over IPC.
+//
+// In sum, when passing a handle to a channel over IPC, use this data structure
+// to work on both Windows and POSIX.
+
+namespace IPC {
+
+struct ChannelHandle {
+  // Note that serialization for this object is defined in the ParamTraits
+  // template specialization in ipc_message_utils.h.
+  ChannelHandle() {}
+  // The name that is passed in should be an absolute path for Posix.
+  // Otherwise there may be a problem in IPC communication between
+  // processes with different working directories.
+  ChannelHandle(const std::string& n) : name(n) {}
+  ChannelHandle(const char* n) : name(n) {}
+#if defined(OS_POSIX)
+  ChannelHandle(const std::string& n, const base::FileDescriptor& s)
+      : name(n), socket(s) {}
+#endif  // defined(OS_POSIX)
+
+  std::string name;
+#if defined(OS_POSIX)
+  base::FileDescriptor socket;
+#endif  // defined(OS_POSIX)
+
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_CHANNEL_HANDLE_H_
diff --git a/ipc/ipc_channel_posix.cc b/ipc/ipc_channel_posix.cc
new file mode 100644 (file)
index 0000000..c358d35
--- /dev/null
@@ -0,0 +1,1217 @@
+// 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 "ipc/ipc_channel_posix.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <string>
+#include <map>
+
+#include "base/command_line.h"
+#include "base/eintr_wrapper.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/global_descriptors_posix.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
+#include "base/process_util.h"
+#include "base/stl_util.h"
+#include "base/string_util.h"
+#include "base/synchronization/lock.h"
+#include "ipc/ipc_descriptors.h"
+#include "ipc/ipc_switches.h"
+#include "ipc/file_descriptor_set_posix.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace IPC {
+
+// IPC channels on Windows use named pipes (CreateNamedPipe()) with
+// channel ids as the pipe names.  Channels on POSIX use sockets as
+// pipes  These don't quite line up.
+//
+// When creating a child subprocess we use a socket pair and the parent side of
+// the fork arranges it such that the initial control channel ends up on the
+// magic file descriptor kPrimaryIPCChannel in the child.  Future
+// connections (file descriptors) can then be passed via that
+// connection via sendmsg().
+//
+// A POSIX IPC channel can also be set up as a server for a bound UNIX domain
+// socket, and will handle multiple connect and disconnect sequences.  Currently
+// it is limited to one connection at a time.
+
+//------------------------------------------------------------------------------
+namespace {
+
+// The PipeMap class works around this quirk related to unit tests:
+//
+// When running as a server, we install the client socket in a
+// specific file descriptor number (@kPrimaryIPCChannel). However, we
+// also have to support the case where we are running unittests in the
+// same process.  (We do not support forking without execing.)
+//
+// Case 1: normal running
+//   The IPC server object will install a mapping in PipeMap from the
+//   name which it was given to the client pipe. When forking the client, the
+//   GetClientFileDescriptorMapping will ensure that the socket is installed in
+//   the magic slot (@kPrimaryIPCChannel). The client will search for the
+//   mapping, but it won't find any since we are in a new process. Thus the
+//   magic fd number is returned. Once the client connects, the server will
+//   close its copy of the client socket and remove the mapping.
+//
+// Case 2: unittests - client and server in the same process
+//   The IPC server will install a mapping as before. The client will search
+//   for a mapping and find out. It duplicates the file descriptor and
+//   connects. Once the client connects, the server will close the original
+//   copy of the client socket and remove the mapping. Thus, when the client
+//   object closes, it will close the only remaining copy of the client socket
+//   in the fd table and the server will see EOF on its side.
+//
+// TODO(port): a client process cannot connect to multiple IPC channels with
+// this scheme.
+
+class PipeMap {
+ public:
+  static PipeMap* GetInstance() {
+    return Singleton<PipeMap>::get();
+  }
+
+  ~PipeMap() {
+    // Shouldn't have left over pipes.
+    DCHECK(map_.empty());
+  }
+
+  // Lookup a given channel id. Return -1 if not found.
+  int Lookup(const std::string& channel_id) {
+    base::AutoLock locked(lock_);
+
+    ChannelToFDMap::const_iterator i = map_.find(channel_id);
+    if (i == map_.end())
+      return -1;
+    return i->second;
+  }
+
+  // Remove the mapping for the given channel id. No error is signaled if the
+  // channel_id doesn't exist
+  void RemoveAndClose(const std::string& channel_id) {
+    base::AutoLock locked(lock_);
+
+    ChannelToFDMap::iterator i = map_.find(channel_id);
+    if (i != map_.end()) {
+      if (HANDLE_EINTR(close(i->second)) < 0)
+        PLOG(ERROR) << "close " << channel_id;
+      map_.erase(i);
+    }
+  }
+
+  // Insert a mapping from @channel_id to @fd. It's a fatal error to insert a
+  // mapping if one already exists for the given channel_id
+  void Insert(const std::string& channel_id, int fd) {
+    base::AutoLock locked(lock_);
+    DCHECK_NE(-1, fd);
+
+    ChannelToFDMap::const_iterator i = map_.find(channel_id);
+    CHECK(i == map_.end()) << "Creating second IPC server (fd " << fd << ") "
+                           << "for '" << channel_id << "' while first "
+                           << "(fd " << i->second << ") still exists";
+    map_[channel_id] = fd;
+  }
+
+ private:
+  base::Lock lock_;
+  typedef std::map<std::string, int> ChannelToFDMap;
+  ChannelToFDMap map_;
+
+  friend struct DefaultSingletonTraits<PipeMap>;
+};
+
+//------------------------------------------------------------------------------
+// Verify that kMaxPipeNameLength is a decent size.
+COMPILE_ASSERT(sizeof(((sockaddr_un*)0)->sun_path) >= kMaxPipeNameLength,
+               BAD_SUN_PATH_LENGTH);
+
+// Creates a unix domain socket bound to the specified name that is listening
+// for connections.
+bool CreateServerUnixDomainSocket(const std::string& pipe_name,
+                                  int* server_listen_fd) {
+  DCHECK(server_listen_fd);
+  DCHECK_GT(pipe_name.length(), 0u);
+  DCHECK_LT(pipe_name.length(), kMaxPipeNameLength);
+
+  if (pipe_name.length() == 0 || pipe_name.length() >= kMaxPipeNameLength) {
+    return false;
+  }
+
+  // Create socket.
+  int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (fd < 0) {
+    return false;
+  }
+
+  // Make socket non-blocking
+  if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+    PLOG(ERROR) << "fcntl(O_NONBLOCK) " << pipe_name;
+    if (HANDLE_EINTR(close(fd)) < 0)
+      PLOG(ERROR) << "close " << pipe_name;
+    return false;
+  }
+
+  // Delete any old FS instances.
+  unlink(pipe_name.c_str());
+
+  // Make sure the path we need exists.
+  FilePath path(pipe_name);
+  FilePath dir_path = path.DirName();
+  if (!file_util::CreateDirectory(dir_path)) {
+    return false;
+  }
+
+  // Create unix_addr structure.
+  struct sockaddr_un unix_addr;
+  memset(&unix_addr, 0, sizeof(unix_addr));
+  unix_addr.sun_family = AF_UNIX;
+  int path_len = snprintf(unix_addr.sun_path, IPC::kMaxPipeNameLength,
+                          "%s", pipe_name.c_str());
+  DCHECK_EQ(static_cast<int>(pipe_name.length()), path_len);
+  size_t unix_addr_len = offsetof(struct sockaddr_un,
+                                       sun_path) + path_len + 1;
+
+  // Bind the socket.
+  if (bind(fd, reinterpret_cast<const sockaddr*>(&unix_addr),
+           unix_addr_len) != 0) {
+    PLOG(ERROR) << "bind " << pipe_name;
+    if (HANDLE_EINTR(close(fd)) < 0)
+      PLOG(ERROR) << "close " << pipe_name;
+    return false;
+  }
+
+  // Start listening on the socket.
+  const int listen_queue_length = 1;
+  if (listen(fd, listen_queue_length) != 0) {
+    PLOG(ERROR) << "listen " << pipe_name;
+    if (HANDLE_EINTR(close(fd)) < 0)
+      PLOG(ERROR) << "close " << pipe_name;
+    return false;
+  }
+
+  *server_listen_fd = fd;
+  return true;
+}
+
+// Accept a connection on a socket we are listening to.
+bool ServerAcceptConnection(int server_listen_fd, int* server_socket) {
+  DCHECK(server_socket);
+
+  int accept_fd = HANDLE_EINTR(accept(server_listen_fd, NULL, 0));
+  if (accept_fd < 0)
+    return false;
+  if (fcntl(accept_fd, F_SETFL, O_NONBLOCK) == -1) {
+    PLOG(ERROR) << "fcntl(O_NONBLOCK) " << accept_fd;
+    if (HANDLE_EINTR(close(accept_fd)) < 0)
+      PLOG(ERROR) << "close " << accept_fd;
+    return false;
+  }
+
+  *server_socket = accept_fd;
+  return true;
+}
+
+bool CreateClientUnixDomainSocket(const std::string& pipe_name,
+                                  int* client_socket) {
+  DCHECK(client_socket);
+  DCHECK_GT(pipe_name.length(), 0u);
+  DCHECK_LT(pipe_name.length(), kMaxPipeNameLength);
+
+  if (pipe_name.length() == 0 || pipe_name.length() >= kMaxPipeNameLength) {
+    return false;
+  }
+
+  // Create socket.
+  int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (fd < 0) {
+    PLOG(ERROR) << "socket " << pipe_name;
+    return false;
+  }
+
+  // Make socket non-blocking
+  if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+    PLOG(ERROR) << "fcntl(O_NONBLOCK) " << pipe_name;
+    if (HANDLE_EINTR(close(fd)) < 0)
+      PLOG(ERROR) << "close " << pipe_name;
+    return false;
+  }
+
+  // Create server side of socket.
+  struct sockaddr_un server_unix_addr;
+  memset(&server_unix_addr, 0, sizeof(server_unix_addr));
+  server_unix_addr.sun_family = AF_UNIX;
+  int path_len = snprintf(server_unix_addr.sun_path, IPC::kMaxPipeNameLength,
+                          "%s", pipe_name.c_str());
+  DCHECK_EQ(static_cast<int>(pipe_name.length()), path_len);
+  size_t server_unix_addr_len = offsetof(struct sockaddr_un,
+                                         sun_path) + path_len + 1;
+
+  if (HANDLE_EINTR(connect(fd, reinterpret_cast<sockaddr*>(&server_unix_addr),
+                           server_unix_addr_len)) != 0) {
+    PLOG(ERROR) << "connect " << pipe_name;
+    if (HANDLE_EINTR(close(fd)) < 0)
+      PLOG(ERROR) << "close " << pipe_name;
+    return false;
+  }
+
+  *client_socket = fd;
+  return true;
+}
+
+bool SocketWriteErrorIsRecoverable() {
+#if defined(OS_MACOSX)
+  // On OS X if sendmsg() is trying to send fds between processes and there
+  // isn't enough room in the output buffer to send the fd structure over
+  // atomically then EMSGSIZE is returned.
+  //
+  // EMSGSIZE presents a problem since the system APIs can only call us when
+  // there's room in the socket buffer and not when there is "enough" room.
+  //
+  // The current behavior is to return to the event loop when EMSGSIZE is
+  // received and hopefull service another FD.  This is however still
+  // technically a busy wait since the event loop will call us right back until
+  // the receiver has read enough data to allow passing the FD over atomically.
+  return errno == EAGAIN || errno == EMSGSIZE;
+#else
+  return errno == EAGAIN;
+#endif  // OS_MACOSX
+}
+
+}  // namespace
+//------------------------------------------------------------------------------
+
+Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle,
+                                  Mode mode, Listener* listener)
+    : mode_(mode),
+      is_blocked_on_write_(false),
+      waiting_connect_(true),
+      message_send_bytes_written_(0),
+      server_listen_pipe_(-1),
+      pipe_(-1),
+      client_pipe_(-1),
+#if defined(IPC_USES_READWRITE)
+      fd_pipe_(-1),
+      remote_fd_pipe_(-1),
+#endif  // IPC_USES_READWRITE
+      pipe_name_(channel_handle.name),
+      listener_(listener),
+      must_unlink_(false) {
+  memset(input_buf_, 0, sizeof(input_buf_));
+  memset(input_cmsg_buf_, 0, sizeof(input_cmsg_buf_));
+  if (!CreatePipe(channel_handle)) {
+    // The pipe may have been closed already.
+    const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
+    // The pipe may have been closed already.
+    LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name
+                 << "\" in " << modestr << " mode";
+  }
+}
+
+Channel::ChannelImpl::~ChannelImpl() {
+  Close();
+}
+
+bool SocketPair(int* fd1, int* fd2) {
+  int pipe_fds[2];
+  if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) {
+    PLOG(ERROR) << "socketpair()";
+    return false;
+  }
+
+  // Set both ends to be non-blocking.
+  if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 ||
+      fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) {
+    PLOG(ERROR) << "fcntl(O_NONBLOCK)";
+    if (HANDLE_EINTR(close(pipe_fds[0])) < 0)
+      PLOG(ERROR) << "close";
+    if (HANDLE_EINTR(close(pipe_fds[1])) < 0)
+      PLOG(ERROR) << "close";
+    return false;
+  }
+
+  *fd1 = pipe_fds[0];
+  *fd2 = pipe_fds[1];
+
+  return true;
+}
+
+bool Channel::ChannelImpl::CreatePipe(
+    const IPC::ChannelHandle& channel_handle) {
+  DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
+
+  // Four possible cases:
+  // 1) It's a channel wrapping a pipe that is given to us.
+  // 2) It's for a named channel, so we create it.
+  // 3) It's for a client that we implement ourself. This is used
+  //    in unittesting.
+  // 4) It's the initial IPC channel:
+  //   4a) Client side: Pull the pipe out of the GlobalDescriptors set.
+  //   4b) Server side: create the pipe.
+
+  int local_pipe = -1;
+  if (channel_handle.socket.fd != -1) {
+    // Case 1 from comment above.
+    local_pipe = channel_handle.socket.fd;
+#if defined(IPC_USES_READWRITE)
+    // Test the socket passed into us to make sure it is nonblocking.
+    // We don't want to call read/write on a blocking socket.
+    int value = fcntl(local_pipe, F_GETFL);
+    if (value == -1) {
+      PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_;
+      return false;
+    }
+    if (!(value & O_NONBLOCK)) {
+      LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK";
+      return false;
+    }
+#endif   // IPC_USES_READWRITE
+  } else if (mode_ & MODE_NAMED_FLAG) {
+    // Case 2 from comment above.
+    if (mode_ & MODE_SERVER_FLAG) {
+      if (!CreateServerUnixDomainSocket(pipe_name_, &local_pipe)) {
+        return false;
+      }
+      must_unlink_ = true;
+    } else if (mode_ & MODE_CLIENT_FLAG) {
+      if (!CreateClientUnixDomainSocket(pipe_name_, &local_pipe)) {
+        return false;
+      }
+    } else {
+      LOG(ERROR) << "Bad mode: " << mode_;
+      return false;
+    }
+  } else {
+    local_pipe = PipeMap::GetInstance()->Lookup(pipe_name_);
+    if (mode_ & MODE_CLIENT_FLAG) {
+      if (local_pipe != -1) {
+        // Case 3 from comment above.
+        // We only allow one connection.
+        local_pipe = HANDLE_EINTR(dup(local_pipe));
+        PipeMap::GetInstance()->RemoveAndClose(pipe_name_);
+      } else {
+        // Case 4a from comment above.
+        // Guard against inappropriate reuse of the initial IPC channel.  If
+        // an IPC channel closes and someone attempts to reuse it by name, the
+        // initial channel must not be recycled here.  http://crbug.com/26754.
+        static bool used_initial_channel = false;
+        if (used_initial_channel) {
+          LOG(FATAL) << "Denying attempt to reuse initial IPC channel for "
+                     << pipe_name_;
+          return false;
+        }
+        used_initial_channel = true;
+
+        local_pipe =
+            base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel);
+      }
+    } else if (mode_ & MODE_SERVER_FLAG) {
+      // Case 4b from comment above.
+      if (local_pipe != -1) {
+        LOG(ERROR) << "Server already exists for " << pipe_name_;
+        return false;
+      }
+      if (!SocketPair(&local_pipe, &client_pipe_))
+        return false;
+      PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_);
+    } else {
+      LOG(ERROR) << "Bad mode: " << mode_;
+      return false;
+    }
+  }
+
+#if defined(IPC_USES_READWRITE)
+  // Create a dedicated socketpair() for exchanging file descriptors.
+  // See comments for IPC_USES_READWRITE for details.
+  if (mode_ & MODE_CLIENT_FLAG) {
+    if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) {
+      return false;
+    }
+  }
+#endif  // IPC_USES_READWRITE
+
+  if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) {
+    server_listen_pipe_ = local_pipe;
+    local_pipe = -1;
+  }
+
+  pipe_ = local_pipe;
+  return true;
+}
+
+bool Channel::ChannelImpl::Connect() {
+  if (server_listen_pipe_ == -1 && pipe_ == -1) {
+    DLOG(INFO) << "Channel creation failed: " << pipe_name_;
+    return false;
+  }
+
+  bool did_connect = true;
+  if (server_listen_pipe_ != -1) {
+    // Watch the pipe for connections, and turn any connections into
+    // active sockets.
+    MessageLoopForIO::current()->WatchFileDescriptor(
+        server_listen_pipe_,
+        true,
+        MessageLoopForIO::WATCH_READ,
+        &server_listen_connection_watcher_,
+        this);
+  } else {
+    did_connect = AcceptConnection();
+  }
+  return did_connect;
+}
+
+bool Channel::ChannelImpl::ProcessIncomingMessages() {
+  ssize_t bytes_read = 0;
+
+  struct msghdr msg = {0};
+  struct iovec iov = {input_buf_, Channel::kReadBufferSize};
+
+  msg.msg_iovlen = 1;
+  msg.msg_control = input_cmsg_buf_;
+
+  for (;;) {
+    msg.msg_iov = &iov;
+
+    if (bytes_read == 0) {
+      if (pipe_ == -1)
+        return false;
+
+      // Read from pipe.
+      // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
+      // is waiting on the pipe.
+#if defined(IPC_USES_READWRITE)
+      if (fd_pipe_ >= 0) {
+        bytes_read = HANDLE_EINTR(read(pipe_, input_buf_,
+                                       Channel::kReadBufferSize));
+        msg.msg_controllen = 0;
+      } else
+#endif  // IPC_USES_READWRITE
+      {
+        msg.msg_controllen = sizeof(input_cmsg_buf_);
+        bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
+      }
+      if (bytes_read < 0) {
+        if (errno == EAGAIN) {
+          return true;
+#if defined(OS_MACOSX)
+        } else if (errno == EPERM) {
+          // On OSX, reading from a pipe with no listener returns EPERM
+          // treat this as a special case to prevent spurious error messages
+          // to the console.
+          return false;
+#endif  // OS_MACOSX
+        } else if (errno == ECONNRESET || errno == EPIPE) {
+          return false;
+        } else {
+          PLOG(ERROR) << "pipe error (" << pipe_ << ")";
+          return false;
+        }
+      } else if (bytes_read == 0) {
+        // The pipe has closed...
+        return false;
+      }
+    }
+    DCHECK(bytes_read);
+
+    if (client_pipe_ != -1) {
+      PipeMap::GetInstance()->RemoveAndClose(pipe_name_);
+      client_pipe_ = -1;
+    }
+
+    // a pointer to an array of |num_wire_fds| file descriptors from the read
+    const int* wire_fds = NULL;
+    unsigned num_wire_fds = 0;
+
+    // walk the list of control messages and, if we find an array of file
+    // descriptors, save a pointer to the array
+
+    // This next if statement is to work around an OSX issue where
+    // CMSG_FIRSTHDR will return non-NULL in the case that controllen == 0.
+    // Here's a test case:
+    //
+    // int main() {
+    // struct msghdr msg;
+    //   msg.msg_control = &msg;
+    //   msg.msg_controllen = 0;
+    //   if (CMSG_FIRSTHDR(&msg))
+    //     printf("Bug found!\n");
+    // }
+    if (msg.msg_controllen > 0) {
+      // On OSX, CMSG_FIRSTHDR doesn't handle the case where controllen is 0
+      // and will return a pointer into nowhere.
+      for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+           cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+        if (cmsg->cmsg_level == SOL_SOCKET &&
+            cmsg->cmsg_type == SCM_RIGHTS) {
+          const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
+          DCHECK_EQ(0U, payload_len % sizeof(int));
+          wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+          num_wire_fds = payload_len / 4;
+
+          if (msg.msg_flags & MSG_CTRUNC) {
+            LOG(ERROR) << "SCM_RIGHTS message was truncated"
+                       << " cmsg_len:" << cmsg->cmsg_len
+                       << " fd:" << pipe_;
+            for (unsigned i = 0; i < num_wire_fds; ++i)
+              if (HANDLE_EINTR(close(wire_fds[i])) < 0)
+                PLOG(ERROR) << "close " << i;
+            return false;
+          }
+          break;
+        }
+      }
+    }
+
+    // Process messages from input buffer.
+    const char *p;
+    const char *end;
+    if (input_overflow_buf_.empty()) {
+      p = input_buf_;
+      end = p + bytes_read;
+    } else {
+      if (input_overflow_buf_.size() >
+         static_cast<size_t>(kMaximumMessageSize - bytes_read)) {
+        input_overflow_buf_.clear();
+        LOG(ERROR) << "IPC message is too big";
+        return false;
+      }
+      input_overflow_buf_.append(input_buf_, bytes_read);
+      p = input_overflow_buf_.data();
+      end = p + input_overflow_buf_.size();
+    }
+
+    // A pointer to an array of |num_fds| file descriptors which includes any
+    // fds that have spilled over from a previous read.
+    const int* fds = NULL;
+    unsigned num_fds = 0;
+    unsigned fds_i = 0;  // the index of the first unused descriptor
+
+    if (input_overflow_fds_.empty()) {
+      fds = wire_fds;
+      num_fds = num_wire_fds;
+    } else {
+      if (num_wire_fds > 0) {
+        const size_t prev_size = input_overflow_fds_.size();
+        input_overflow_fds_.resize(prev_size + num_wire_fds);
+        memcpy(&input_overflow_fds_[prev_size], wire_fds,
+               num_wire_fds * sizeof(int));
+      }
+      fds = &input_overflow_fds_[0];
+      num_fds = input_overflow_fds_.size();
+    }
+
+    while (p < end) {
+      const char* message_tail = Message::FindNext(p, end);
+      if (message_tail) {
+        int len = static_cast<int>(message_tail - p);
+        Message m(p, len);
+        const uint16 header_fds = m.header()->num_fds;
+        if (header_fds) {
+          // the message has file descriptors
+          const char* error = NULL;
+          if (header_fds > num_fds - fds_i) {
+            // the message has been completely received, but we didn't get
+            // enough file descriptors.
+#if defined(IPC_USES_READWRITE)
+            char dummy;
+            struct iovec fd_pipe_iov = { &dummy, 1 };
+            msg.msg_iov = &fd_pipe_iov;
+            msg.msg_controllen = sizeof(input_cmsg_buf_);
+            ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT));
+            if (n == 1 && msg.msg_controllen > 0) {
+              for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+                   cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+                if (cmsg->cmsg_level == SOL_SOCKET &&
+                    cmsg->cmsg_type == SCM_RIGHTS) {
+                  const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
+                  DCHECK_EQ(0U, payload_len % sizeof(int));
+                  wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+                  num_wire_fds = payload_len / 4;
+
+                  if (msg.msg_flags & MSG_CTRUNC) {
+                    LOG(ERROR) << "SCM_RIGHTS message was truncated"
+                               << " cmsg_len:" << cmsg->cmsg_len
+                               << " fd:" << pipe_;
+                    for (unsigned i = 0; i < num_wire_fds; ++i)
+                      if (HANDLE_EINTR(close(wire_fds[i])) < 0)
+                        PLOG(ERROR) << "close " << i;
+                    return false;
+                  }
+                  break;
+                }
+              }
+              if (input_overflow_fds_.empty()) {
+                fds = wire_fds;
+                num_fds = num_wire_fds;
+              } else {
+                if (num_wire_fds > 0) {
+                  const size_t prev_size = input_overflow_fds_.size();
+                  input_overflow_fds_.resize(prev_size + num_wire_fds);
+                  memcpy(&input_overflow_fds_[prev_size], wire_fds,
+                         num_wire_fds * sizeof(int));
+                }
+                fds = &input_overflow_fds_[0];
+                num_fds = input_overflow_fds_.size();
+              }
+            }
+            if (header_fds > num_fds - fds_i)
+#endif  // IPC_USES_READWRITE
+              error = "Message needs unreceived descriptors";
+          }
+
+          if (header_fds >
+              FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) {
+            // There are too many descriptors in this message
+            error = "Message requires an excessive number of descriptors";
+          }
+
+          if (error) {
+            LOG(WARNING) << error
+                         << " channel:" << this
+                         << " message-type:" << m.type()
+                         << " header()->num_fds:" << header_fds
+                         << " num_fds:" << num_fds
+                         << " fds_i:" << fds_i;
+#if defined(CHROMIUM_SELINUX)
+            LOG(WARNING) << "In the case of SELinux this can be caused when "
+                            "using a --user-data-dir to which the default "
+                            "policy doesn't give the renderer access to. ";
+#endif  // CHROMIUM_SELINUX
+            // close the existing file descriptors so that we don't leak them
+            for (unsigned i = fds_i; i < num_fds; ++i)
+              if (HANDLE_EINTR(close(fds[i])) < 0)
+                PLOG(ERROR) << "close " << i;
+            input_overflow_fds_.clear();
+            // abort the connection
+            return false;
+          }
+
+          m.file_descriptor_set()->SetDescriptors(
+              &fds[fds_i], header_fds);
+          fds_i += header_fds;
+        }
+        DVLOG(2) << "received message on channel @" << this
+                 << " with type " << m.type() << " on fd " << pipe_;
+        if (IsHelloMessage(&m)) {
+          // The Hello message contains only the process id.
+          void *iter = NULL;
+          int pid;
+          if (!m.ReadInt(&iter, &pid)) {
+            NOTREACHED();
+          }
+#if defined(IPC_USES_READWRITE)
+          if (mode_ & MODE_SERVER_FLAG) {
+            // With IPC_USES_READWRITE, the Hello message from the client to the
+            // server also contains the fd_pipe_, which  will be used for all
+            // subsequent file descriptor passing.
+            DCHECK_EQ(m.file_descriptor_set()->size(), 1U);
+            base::FileDescriptor descriptor;
+            if (!m.ReadFileDescriptor(&iter, &descriptor)) {
+              NOTREACHED();
+            }
+            fd_pipe_ = descriptor.fd;
+            CHECK(descriptor.auto_close);
+          }
+#endif  // IPC_USES_READWRITE
+          listener_->OnChannelConnected(pid);
+        } else {
+          listener_->OnMessageReceived(m);
+        }
+        p = message_tail;
+      } else {
+        // Last message is partial.
+        break;
+      }
+      input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]);
+      fds_i = 0;
+      fds = vector_as_array(&input_overflow_fds_);
+      num_fds = input_overflow_fds_.size();
+    }
+    input_overflow_buf_.assign(p, end - p);
+    input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]);
+
+    // When the input data buffer is empty, the overflow fds should be too. If
+    // this is not the case, we probably have a rogue renderer which is trying
+    // to fill our descriptor table.
+    if (input_overflow_buf_.empty() && !input_overflow_fds_.empty()) {
+      // We close these descriptors in Close()
+      return false;
+    }
+
+    bytes_read = 0;  // Get more data.
+  }
+}
+
+bool Channel::ChannelImpl::ProcessOutgoingMessages() {
+  DCHECK(!waiting_connect_);  // Why are we trying to send messages if there's
+                              // no connection?
+  if (output_queue_.empty())
+    return true;
+
+  if (pipe_ == -1)
+    return false;
+
+  // Write out all the messages we can till the write blocks or there are no
+  // more outgoing messages.
+  while (!output_queue_.empty()) {
+    Message* msg = output_queue_.front();
+
+    size_t amt_to_write = msg->size() - message_send_bytes_written_;
+    DCHECK_NE(0U, amt_to_write);
+    const char* out_bytes = reinterpret_cast<const char*>(msg->data()) +
+        message_send_bytes_written_;
+
+    struct msghdr msgh = {0};
+    struct iovec iov = {const_cast<char*>(out_bytes), amt_to_write};
+    msgh.msg_iov = &iov;
+    msgh.msg_iovlen = 1;
+    char buf[CMSG_SPACE(
+        sizeof(int[FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE]))];
+
+    ssize_t bytes_written = 1;
+    int fd_written = -1;
+/*
+    if (message_send_bytes_written_ == 0 &&
+        !msg->file_descriptor_set()->empty()) {
+      // This is the first chunk of a message which has descriptors to send
+      struct cmsghdr *cmsg;
+      const unsigned num_fds = msg->file_descriptor_set()->size();
+
+      DCHECK_LE(num_fds, FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE);
+      if (msg->file_descriptor_set()->ContainsDirectoryDescriptor()) {
+        LOG(FATAL) << "Panic: attempting to transport directory descriptor over"
+                      " IPC. Aborting to maintain sandbox isolation.";
+        // If you have hit this then something tried to send a file descriptor
+        // to a directory over an IPC channel. Since IPC channels span
+        // sandboxes this is very bad: the receiving process can use openat
+        // with ".." elements in the path in order to reach the real
+        // filesystem.
+      }
+
+      msgh.msg_control = buf;
+      msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
+      cmsg = CMSG_FIRSTHDR(&msgh);
+      cmsg->cmsg_level = SOL_SOCKET;
+      cmsg->cmsg_type = SCM_RIGHTS;
+      cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
+      msg->file_descriptor_set()->GetDescriptors(
+          reinterpret_cast<int*>(CMSG_DATA(cmsg)));
+      msgh.msg_controllen = cmsg->cmsg_len;
+
+      // DCHECK_LE above already checks that
+      // num_fds < MAX_DESCRIPTORS_PER_MESSAGE so no danger of overflow.
+      msg->header()->num_fds = static_cast<uint16>(num_fds);
+
+#if defined(IPC_USES_READWRITE)
+      if (!IsHelloMessage(msg)) {
+        // Only the Hello message sends the file descriptor with the message.
+        // Subsequently, we can send file descriptors on the dedicated
+        // fd_pipe_ which makes Seccomp sandbox operation more efficient.
+        struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 };
+        msgh.msg_iov = &fd_pipe_iov;
+        fd_written = fd_pipe_;
+        bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT));
+        msgh.msg_iov = &iov;
+        msgh.msg_controllen = 0;
+        if (bytes_written > 0) {
+          msg->file_descriptor_set()->CommitAll();
+        }
+      }
+#endif  // IPC_USES_READWRITE
+    }
+*/
+    if (bytes_written == 1) {
+      fd_written = pipe_;
+#if defined(IPC_USES_READWRITE)
+      if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(msg)) {
+        DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
+      }
+      if (!msgh.msg_controllen) {
+        bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write));
+      } else
+#endif  // IPC_USES_READWRITE
+      {
+        bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT));
+      }
+    }
+    if (bytes_written > 0)
+      msg->file_descriptor_set()->CommitAll();
+
+    if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) {
+#if defined(OS_MACOSX)
+      // On OSX writing to a pipe with no listener returns EPERM.
+      if (errno == EPERM) {
+        Close();
+        return false;
+      }
+#endif  // OS_MACOSX
+      if (errno == EPIPE) {
+        Close();
+        return false;
+      }
+      PLOG(ERROR) << "pipe error on "
+                  << fd_written
+                  << " Currently writing message of size: "
+                  << msg->size();
+      return false;
+    }
+
+    if (static_cast<size_t>(bytes_written) != amt_to_write) {
+      if (bytes_written > 0) {
+        // If write() fails with EAGAIN then bytes_written will be -1.
+        message_send_bytes_written_ += bytes_written;
+      }
+
+      // Tell libevent to call us back once things are unblocked.
+      is_blocked_on_write_ = true;
+      MessageLoopForIO::current()->WatchFileDescriptor(
+          pipe_,
+          false,  // One shot
+          MessageLoopForIO::WATCH_WRITE,
+          &write_watcher_,
+          this);
+      return true;
+    } else {
+      message_send_bytes_written_ = 0;
+
+      // Message sent OK!
+      DVLOG(2) << "sent message @" << msg << " on channel @" << this
+               << " with type " << msg->type() << " on fd " << pipe_;
+      delete output_queue_.front();
+      output_queue_.pop();
+    }
+  }
+  return true;
+}
+
+bool Channel::ChannelImpl::Send(Message* message) {
+  DVLOG(2) << "sending message @" << message << " on channel @" << this
+           << " with type " << message->type()
+           << " (" << output_queue_.size() << " in queue)";
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  Logging::GetInstance()->OnSendMessage(message, "");
+#endif  // IPC_MESSAGE_LOG_ENABLED
+
+  output_queue_.push(message);
+  if (!is_blocked_on_write_ && !waiting_connect_) {
+    return ProcessOutgoingMessages();
+  }
+
+  return true;
+}
+
+int Channel::ChannelImpl::GetClientFileDescriptor() const {
+  return client_pipe_;
+}
+
+bool Channel::ChannelImpl::AcceptsConnections() const {
+  return server_listen_pipe_ != -1;
+}
+
+bool Channel::ChannelImpl::HasAcceptedConnection() const {
+  return AcceptsConnections() && pipe_ != -1;
+}
+
+bool Channel::ChannelImpl::GetClientEuid(uid_t* client_euid) const {
+  DCHECK(HasAcceptedConnection());
+#if defined(OS_MACOSX)
+  uid_t peer_euid;
+  gid_t peer_gid;
+  if (getpeereid(pipe_, &peer_euid, &peer_gid) != 0) {
+    PLOG(ERROR) << "getpeereid " << pipe_;
+    return false;
+  }
+  *client_euid = peer_euid;
+  return true;
+#elif defined(OS_SOLARIS)
+  return false;
+#else
+  struct ucred cred;
+  socklen_t cred_len = sizeof(cred);
+  if (getsockopt(pipe_, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) != 0) {
+    PLOG(ERROR) << "getsockopt " << pipe_;
+    return false;
+  }
+  if (cred_len < sizeof(cred)) {
+    NOTREACHED() << "Truncated ucred from SO_PEERCRED?";
+    return false;
+  }
+  *client_euid = cred.uid;
+  return true;
+#endif
+}
+
+void Channel::ChannelImpl::ResetToAcceptingConnectionState() {
+  // Unregister libevent for the unix domain socket and close it.
+  read_watcher_.StopWatchingFileDescriptor();
+  write_watcher_.StopWatchingFileDescriptor();
+  if (pipe_ != -1) {
+    if (HANDLE_EINTR(close(pipe_)) < 0)
+      PLOG(ERROR) << "close pipe_ " << pipe_name_;
+    pipe_ = -1;
+  }
+#if defined(IPC_USES_READWRITE)
+  if (fd_pipe_ != -1) {
+    if (HANDLE_EINTR(close(fd_pipe_)) < 0)
+      PLOG(ERROR) << "close fd_pipe_ " << pipe_name_;
+    fd_pipe_ = -1;
+  }
+  if (remote_fd_pipe_ != -1) {
+    if (HANDLE_EINTR(close(remote_fd_pipe_)) < 0)
+      PLOG(ERROR) << "close remote_fd_pipe_ " << pipe_name_;
+    remote_fd_pipe_ = -1;
+  }
+#endif  // IPC_USES_READWRITE
+
+  while (!output_queue_.empty()) {
+    Message* m = output_queue_.front();
+    output_queue_.pop();
+    delete m;
+  }
+
+  // Close any outstanding, received file descriptors.
+  for (std::vector<int>::iterator
+       i = input_overflow_fds_.begin(); i != input_overflow_fds_.end(); ++i) {
+    if (HANDLE_EINTR(close(*i)) < 0)
+      PLOG(ERROR) << "close";
+  }
+  input_overflow_fds_.clear();
+}
+
+// static
+bool Channel::ChannelImpl::IsNamedServerInitialized(
+    const std::string& channel_id) {
+  return file_util::PathExists(FilePath(channel_id));
+}
+
+// Called by libevent when we can read from the pipe without blocking.
+void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) {
+  bool send_server_hello_msg = false;
+  if (fd == server_listen_pipe_) {
+    int new_pipe = 0;
+    if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe)) {
+      Close();
+      listener_->OnChannelListenError();
+    }
+
+    if (pipe_ != -1) {
+      // We already have a connection. We only handle one at a time.
+      // close our new descriptor.
+      if (HANDLE_EINTR(shutdown(new_pipe, SHUT_RDWR)) < 0)
+        PLOG(ERROR) << "shutdown " << pipe_name_;
+      if (HANDLE_EINTR(close(new_pipe)) < 0)
+        PLOG(ERROR) << "close " << pipe_name_;
+      listener_->OnChannelDenied();
+      return;
+    }
+    pipe_ = new_pipe;
+
+    if ((mode_ & MODE_OPEN_ACCESS_FLAG) == 0) {
+      // Verify that the IPC channel peer is running as the same user.
+      uid_t client_euid;
+      if (!GetClientEuid(&client_euid)) {
+        LOG(ERROR) << "Unable to query client euid";
+        ResetToAcceptingConnectionState();
+        return;
+      }
+      if (client_euid != geteuid()) {
+        LOG(WARNING) << "Client euid is not authorised";
+        ResetToAcceptingConnectionState();
+        return;
+      }
+    }
+
+    if (!AcceptConnection()) {
+      NOTREACHED() << "AcceptConnection should not fail on server";
+    }
+    send_server_hello_msg = true;
+    waiting_connect_ = false;
+  } else if (fd == pipe_) {
+    if (waiting_connect_ && (mode_ & MODE_SERVER_FLAG)) {
+      send_server_hello_msg = true;
+      waiting_connect_ = false;
+    }
+    if (!ProcessIncomingMessages()) {
+      // ClosePipeOnError may delete this object, so we mustn't call
+      // ProcessOutgoingMessages.
+      send_server_hello_msg = false;
+      ClosePipeOnError();
+    }
+  } else {
+    NOTREACHED() << "Unknown pipe " << fd;
+  }
+
+  // If we're a server and handshaking, then we want to make sure that we
+  // only send our handshake message after we've processed the client's.
+  // This gives us a chance to kill the client if the incoming handshake
+  // is invalid.
+  if (send_server_hello_msg) {
+    ProcessOutgoingMessages();
+  }
+}
+
+// Called by libevent when we can write to the pipe without blocking.
+void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) {
+  DCHECK_EQ(pipe_, fd);
+  is_blocked_on_write_ = false;
+  if (!ProcessOutgoingMessages()) {
+    ClosePipeOnError();
+  }
+}
+
+bool Channel::ChannelImpl::AcceptConnection() {
+  MessageLoopForIO::current()->WatchFileDescriptor(pipe_,
+                                                   true,
+                                                   MessageLoopForIO::WATCH_READ,
+                                                   &read_watcher_,
+                                                   this);
+  QueueHelloMessage();
+
+  if (mode_ & MODE_CLIENT_FLAG) {
+    // If we are a client we want to send a hello message out immediately.
+    // In server mode we will send a hello message when we receive one from a
+    // client.
+    waiting_connect_ = false;
+    return ProcessOutgoingMessages();
+  } else if (mode_ & MODE_SERVER_FLAG) {
+    waiting_connect_ = true;
+    return true;
+  } else {
+    NOTREACHED();
+    return false;
+  }
+}
+
+void Channel::ChannelImpl::ClosePipeOnError() {
+  if (HasAcceptedConnection()) {
+    ResetToAcceptingConnectionState();
+    listener_->OnChannelError();
+  } else {
+    Close();
+    if (AcceptsConnections()) {
+      listener_->OnChannelListenError();
+    } else {
+      listener_->OnChannelError();
+    }
+  }
+}
+
+void Channel::ChannelImpl::QueueHelloMessage() {
+  // Create the Hello message
+  scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
+                                      HELLO_MESSAGE_TYPE,
+                                      IPC::Message::PRIORITY_NORMAL));
+
+  if (!msg->WriteInt(base::GetCurrentProcId())) {
+    NOTREACHED() << "Unable to pickle hello message proc id";
+  }
+#if defined(IPC_USES_READWRITE)
+  scoped_ptr<Message> hello;
+  if (remote_fd_pipe_ != -1) {
+    if (!msg->WriteFileDescriptor(base::FileDescriptor(remote_fd_pipe_,
+                                                       false))) {
+      NOTREACHED() << "Unable to pickle hello message file descriptors";
+    }
+    DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
+  }
+#endif  // IPC_USES_READWRITE
+  output_queue_.push(msg.release());
+}
+
+bool Channel::ChannelImpl::IsHelloMessage(const Message* m) const {
+  return m->routing_id() == MSG_ROUTING_NONE && m->type() == HELLO_MESSAGE_TYPE;
+}
+
+void Channel::ChannelImpl::Close() {
+  // Close can be called multiple time, so we need to make sure we're
+  // idempotent.
+
+  ResetToAcceptingConnectionState();
+
+  if (must_unlink_) {
+    unlink(pipe_name_.c_str());
+    must_unlink_ = false;
+  }
+  if (server_listen_pipe_ != -1) {
+    if (HANDLE_EINTR(close(server_listen_pipe_)) < 0)
+      PLOG(ERROR) << "close " << server_listen_pipe_;
+    server_listen_pipe_ = -1;
+    // Unregister libevent for the listening socket and close it.
+    server_listen_connection_watcher_.StopWatchingFileDescriptor();
+  }
+
+  if (client_pipe_ != -1) {
+    PipeMap::GetInstance()->RemoveAndClose(pipe_name_);
+    client_pipe_ = -1;
+  }
+}
+
+//------------------------------------------------------------------------------
+// Channel's methods simply call through to ChannelImpl.
+Channel::Channel(const IPC::ChannelHandle& channel_handle, Mode mode,
+                 Listener* listener)
+    : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) {
+}
+
+Channel::~Channel() {
+  delete channel_impl_;
+}
+
+bool Channel::Connect() {
+  return channel_impl_->Connect();
+}
+
+void Channel::Close() {
+  channel_impl_->Close();
+}
+
+void Channel::set_listener(Listener* listener) {
+  channel_impl_->set_listener(listener);
+}
+
+bool Channel::Send(Message* message) {
+  return channel_impl_->Send(message);
+}
+
+int Channel::GetClientFileDescriptor() const {
+  return channel_impl_->GetClientFileDescriptor();
+}
+
+bool Channel::AcceptsConnections() const {
+  return channel_impl_->AcceptsConnections();
+}
+
+bool Channel::HasAcceptedConnection() const {
+  return channel_impl_->HasAcceptedConnection();
+}
+
+bool Channel::GetClientEuid(uid_t* client_euid) const {
+  return channel_impl_->GetClientEuid(client_euid);
+}
+
+void Channel::ResetToAcceptingConnectionState() {
+  channel_impl_->ResetToAcceptingConnectionState();
+}
+
+// static
+bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
+  return ChannelImpl::IsNamedServerInitialized(channel_id);
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_channel_posix.h b/ipc/ipc_channel_posix.h
new file mode 100644 (file)
index 0000000..b66b1fc
--- /dev/null
@@ -0,0 +1,161 @@
+// 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 IPC_IPC_CHANNEL_POSIX_H_
+#define IPC_IPC_CHANNEL_POSIX_H_
+#pragma once
+
+#include "ipc/ipc_channel.h"
+
+#include <sys/socket.h>  // for CMSG macros
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/message_loop.h"
+#include "ipc/file_descriptor_set_posix.h"
+
+#if !defined(OS_MACOSX)
+// On Linux, the seccomp sandbox makes it very expensive to call
+// recvmsg() and sendmsg(). The restriction on calling read() and write(), which
+// are cheap, is that we can't pass file descriptors over them.
+//
+// As we cannot anticipate when the sender will provide us with file
+// descriptors, we have to make the decision about whether we call read() or
+// recvmsg() before we actually make the call. The easiest option is to
+// create a dedicated socketpair() for exchanging file descriptors. Any file
+// descriptors are split out of a message, with the non-file-descriptor payload
+// going over the normal connection, and the file descriptors being sent
+// separately over the other channel. When read()ing from a channel, we'll
+// notice if the message was supposed to have come with file descriptors and
+// use recvmsg on the other socketpair to retrieve them and combine them
+// back with the rest of the message.
+//
+// Mac can also run in IPC_USES_READWRITE mode if necessary, but at this time
+// doesn't take a performance hit from recvmsg and sendmsg, so it doesn't
+// make sense to waste resources on having the separate dedicated socketpair.
+// It is however useful for debugging between Linux and Mac to be able to turn
+// this switch 'on' on the Mac as well.
+//
+// The HELLO message from the client to the server is always sent using
+// sendmsg because it will contain the file descriptor that the server
+// needs to send file descriptors in later messages.
+#define IPC_USES_READWRITE 1
+#endif
+
+namespace IPC {
+
+class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
+ public:
+  // Mirror methods of Channel, see ipc_channel.h for description.
+  ChannelImpl(const IPC::ChannelHandle& channel_handle, Mode mode,
+              Listener* listener);
+  virtual ~ChannelImpl();
+  bool Connect();
+  void Close();
+  void set_listener(Listener* listener) { listener_ = listener; }
+  bool Send(Message* message);
+  int GetClientFileDescriptor() const;
+  bool AcceptsConnections() const;
+  bool HasAcceptedConnection() const;
+  bool GetClientEuid(uid_t* client_euid) const;
+  void ResetToAcceptingConnectionState();
+  static bool IsNamedServerInitialized(const std::string& channel_id);
+
+ private:
+  bool CreatePipe(const IPC::ChannelHandle& channel_handle);
+
+  bool ProcessIncomingMessages();
+  bool ProcessOutgoingMessages();
+
+  bool AcceptConnection();
+  void ClosePipeOnError();
+  void QueueHelloMessage();
+  bool IsHelloMessage(const Message* m) const;
+
+  // MessageLoopForIO::Watcher implementation.
+  virtual void OnFileCanReadWithoutBlocking(int fd);
+  virtual void OnFileCanWriteWithoutBlocking(int fd);
+
+  Mode mode_;
+
+  // After accepting one client connection on our server socket we want to
+  // stop listening.
+  MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_;
+  MessageLoopForIO::FileDescriptorWatcher read_watcher_;
+  MessageLoopForIO::FileDescriptorWatcher write_watcher_;
+
+  // Indicates whether we're currently blocked waiting for a write to complete.
+  bool is_blocked_on_write_;
+  bool waiting_connect_;
+
+  // If sending a message blocks then we use this variable
+  // to keep track of where we are.
+  size_t message_send_bytes_written_;
+
+  // File descriptor we're listening on for new connections if we listen
+  // for connections.
+  int server_listen_pipe_;
+
+  // The pipe used for communication.
+  int pipe_;
+
+  // For a server, the client end of our socketpair() -- the other end of our
+  // pipe_ that is passed to the client.
+  int client_pipe_;
+
+#if defined(IPC_USES_READWRITE)
+  // Linux/BSD use a dedicated socketpair() for passing file descriptors.
+  int fd_pipe_;
+  int remote_fd_pipe_;
+#endif
+
+  // The "name" of our pipe.  On Windows this is the global identifier for
+  // the pipe.  On POSIX it's used as a key in a local map of file descriptors.
+  std::string pipe_name_;
+
+  Listener* listener_;
+
+  // Messages to be sent are queued here.
+  std::queue<Message*> output_queue_;
+
+  // We read from the pipe into this buffer
+  char input_buf_[Channel::kReadBufferSize];
+
+  enum {
+    // We assume a worst case: kReadBufferSize bytes of messages, where each
+    // message has no payload and a full complement of descriptors.
+    MAX_READ_FDS = (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) *
+                   FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE,
+  };
+
+  // This is a control message buffer large enough to hold kMaxReadFDs
+#if defined(OS_MACOSX)
+  // TODO(agl): OSX appears to have non-constant CMSG macros!
+  char input_cmsg_buf_[1024];
+#else
+  char input_cmsg_buf_[CMSG_SPACE(sizeof(int) * MAX_READ_FDS)];
+#endif
+
+  // Large messages that span multiple pipe buffers, get built-up using
+  // this buffer.
+  std::string input_overflow_buf_;
+  std::vector<int> input_overflow_fds_;
+
+  // True if we are responsible for unlinking the unix domain socket file.
+  bool must_unlink_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelImpl);
+};
+
+// The maximum length of the name of a pipe for MODE_NAMED_SERVER or
+// MODE_NAMED_CLIENT if you want to pass in your own socket.
+// The standard size on linux is 108, mac is 104. To maintain consistency
+// across platforms we standardize on the smaller value.
+static const size_t kMaxPipeNameLength = 104;
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_CHANNEL_POSIX_H_
diff --git a/ipc/ipc_channel_posix_unittest.cc b/ipc/ipc_channel_posix_unittest.cc
new file mode 100644 (file)
index 0000000..14ecc60
--- /dev/null
@@ -0,0 +1,389 @@
+// 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.
+
+// These tests are POSIX only.
+
+#include "ipc/ipc_channel_posix.h"
+
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "base/basictypes.h"
+#include "base/eintr_wrapper.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
+#include "testing/multiprocess_func_list.h"
+
+namespace {
+
+enum {
+  QUIT_MESSAGE = 47
+};
+
+class IPCChannelPosixTestListener : public IPC::Channel::Listener {
+ public:
+  enum STATUS {
+    DISCONNECTED,
+    MESSAGE_RECEIVED,
+    CHANNEL_ERROR,
+    CONNECTED,
+    DENIED,
+    LISTEN_ERROR
+  };
+
+  IPCChannelPosixTestListener(bool quit_only_on_message)
+      : status_(DISCONNECTED), quit_only_on_message_(quit_only_on_message) {}
+
+  virtual ~IPCChannelPosixTestListener() {}
+
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+    EXPECT_EQ(message.type(), QUIT_MESSAGE);
+    status_ = MESSAGE_RECEIVED;
+    QuitRunLoop();
+    return true;
+  }
+
+  virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
+    status_ = CONNECTED;
+    if (!quit_only_on_message_) {
+      QuitRunLoop();
+    }
+  }
+
+  virtual void OnChannelError() OVERRIDE {
+    status_ = CHANNEL_ERROR;
+    if (!quit_only_on_message_) {
+      QuitRunLoop();
+    }
+  }
+
+  virtual void OnChannelDenied() OVERRIDE {
+    status_ = DENIED;
+    if (!quit_only_on_message_) {
+      QuitRunLoop();
+    }
+  }
+
+  virtual void OnChannelListenError() OVERRIDE {
+    status_ = LISTEN_ERROR;
+    if (!quit_only_on_message_) {
+      QuitRunLoop();
+    }
+  }
+
+  STATUS status() { return status_; }
+
+  void QuitRunLoop() {
+    MessageLoopForIO::current()->QuitNow();
+  }
+
+ private:
+  // The current status of the listener.
+  STATUS status_;
+  // If |quit_only_on_message_| then the listener will only break out of
+  // the run loop when the QUIT_MESSAGE is received.
+  bool quit_only_on_message_;
+};
+
+}  // namespace
+
+class IPCChannelPosixTest : public base::MultiProcessTest {
+ public:
+  static const char kConnectionSocketTestName[];
+  static void SetUpSocket(IPC::ChannelHandle *handle,
+                          IPC::Channel::Mode mode);
+  static void SpinRunLoop(int milliseconds);
+
+ protected:
+  virtual void SetUp();
+  virtual void TearDown();
+
+private:
+  scoped_ptr<MessageLoopForIO> message_loop_;
+};
+
+const char IPCChannelPosixTest::kConnectionSocketTestName[] =
+    "/var/tmp/chrome_IPCChannelPosixTest__ConnectionSocket";
+
+void IPCChannelPosixTest::SetUp() {
+  MultiProcessTest::SetUp();
+  // Construct a fresh IO Message loop for the duration of each test.
+  message_loop_.reset(new MessageLoopForIO());
+}
+
+void IPCChannelPosixTest::TearDown() {
+  message_loop_.reset(NULL);
+  MultiProcessTest::TearDown();
+}
+
+// Create up a socket and bind and listen to it, or connect it
+// depending on the |mode|.
+void IPCChannelPosixTest::SetUpSocket(IPC::ChannelHandle *handle,
+                                      IPC::Channel::Mode mode) {
+  const std::string& name = handle->name;
+
+  int socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+  ASSERT_GE(socket_fd, 0) << name;
+  ASSERT_GE(fcntl(socket_fd, F_SETFL, O_NONBLOCK), 0);
+  struct sockaddr_un server_address = { 0 };
+  memset(&server_address, 0, sizeof(server_address));
+  server_address.sun_family = AF_UNIX;
+  int path_len = snprintf(server_address.sun_path, IPC::kMaxPipeNameLength,
+                          "%s", name.c_str());
+  DCHECK_EQ(static_cast<int>(name.length()), path_len);
+  size_t server_address_len = offsetof(struct sockaddr_un,
+                                       sun_path) + path_len + 1;
+
+  if (mode == IPC::Channel::MODE_NAMED_SERVER) {
+    // Only one server at a time. Cleanup garbage if it exists.
+    unlink(name.c_str());
+      // Make sure the path we need exists.
+    FilePath path(name);
+    FilePath dir_path = path.DirName();
+    ASSERT_TRUE(file_util::CreateDirectory(dir_path));
+    ASSERT_GE(bind(socket_fd,
+                   reinterpret_cast<struct sockaddr *>(&server_address),
+                   server_address_len), 0) << server_address.sun_path
+                                           << ": " << strerror(errno)
+                                           << "(" << errno << ")";
+    ASSERT_GE(listen(socket_fd, SOMAXCONN), 0) << server_address.sun_path
+                                               << ": " << strerror(errno)
+                                               << "(" << errno << ")";
+  } else if (mode == IPC::Channel::MODE_NAMED_CLIENT) {
+    ASSERT_GE(connect(socket_fd,
+                      reinterpret_cast<struct sockaddr *>(&server_address),
+                      server_address_len), 0) << server_address.sun_path
+                                              << ": " << strerror(errno)
+                                              << "(" << errno << ")";
+  } else {
+    FAIL() << "Unknown mode " << mode;
+  }
+  handle->socket.fd = socket_fd;
+}
+
+void IPCChannelPosixTest::SpinRunLoop(int milliseconds) {
+  MessageLoopForIO *loop = MessageLoopForIO::current();
+  // Post a quit task so that this loop eventually ends and we don't hang
+  // in the case of a bad test. Usually, the run loop will quit sooner than
+  // that because all tests use a IPCChannelPosixTestListener which quits the
+  // current run loop on any channel activity.
+  loop->PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask(), milliseconds);
+  loop->Run();
+}
+
+TEST_F(IPCChannelPosixTest, BasicListen) {
+  // Test creating a socket that is listening.
+  IPC::ChannelHandle handle("/var/tmp/IPCChannelPosixTest_BasicListen");
+  SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER);
+  unlink(handle.name.c_str());
+  IPC::Channel channel(handle, IPC::Channel::MODE_NAMED_SERVER, NULL);
+  ASSERT_TRUE(channel.Connect());
+  ASSERT_TRUE(channel.AcceptsConnections());
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+  channel.ResetToAcceptingConnectionState();
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+}
+
+TEST_F(IPCChannelPosixTest, BasicConnected) {
+  // Test creating a socket that is connected.
+  int pipe_fds[2];
+  ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds));
+  std::string socket_name("/var/tmp/IPCChannelPosixTest_BasicConnected");
+  ASSERT_GE(fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK), 0);
+
+  base::FileDescriptor fd(pipe_fds[0], false);
+  IPC::ChannelHandle handle(socket_name, fd);
+  IPC::Channel channel(handle, IPC::Channel::MODE_SERVER, NULL);
+  ASSERT_TRUE(channel.Connect());
+  ASSERT_FALSE(channel.AcceptsConnections());
+  channel.Close();
+  ASSERT_TRUE(HANDLE_EINTR(close(pipe_fds[1])) == 0);
+
+  // Make sure that we can use the socket that is created for us by
+  // a standard channel.
+  IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL);
+  ASSERT_TRUE(channel2.Connect());
+  ASSERT_FALSE(channel2.AcceptsConnections());
+}
+
+TEST_F(IPCChannelPosixTest, AdvancedConnected) {
+  // Test creating a connection to an external process.
+  IPCChannelPosixTestListener listener(false);
+  IPC::ChannelHandle chan_handle(kConnectionSocketTestName);
+  SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER);
+  IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
+  ASSERT_TRUE(channel.Connect());
+  ASSERT_TRUE(channel.AcceptsConnections());
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+
+  base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc",
+                                          false);
+  ASSERT_TRUE(handle);
+  SpinRunLoop(TestTimeouts::action_max_timeout_ms());
+  ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
+  ASSERT_TRUE(channel.HasAcceptedConnection());
+  IPC::Message* message = new IPC::Message(0, // routing_id
+                                           QUIT_MESSAGE, // message type
+                                           IPC::Message::PRIORITY_NORMAL);
+  channel.Send(message);
+  SpinRunLoop(TestTimeouts::action_timeout_ms());
+  int exit_code = 0;
+  EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
+  EXPECT_EQ(0, exit_code);
+  ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+}
+
+TEST_F(IPCChannelPosixTest, ResetState) {
+  // Test creating a connection to an external process. Close the connection,
+  // but continue to listen and make sure another external process can connect
+  // to us.
+  IPCChannelPosixTestListener listener(false);
+  IPC::ChannelHandle chan_handle(kConnectionSocketTestName);
+  SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER);
+  IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
+  ASSERT_TRUE(channel.Connect());
+  ASSERT_TRUE(channel.AcceptsConnections());
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+
+  base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc",
+                                          false);
+  ASSERT_TRUE(handle);
+  SpinRunLoop(TestTimeouts::action_max_timeout_ms());
+  ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
+  ASSERT_TRUE(channel.HasAcceptedConnection());
+  channel.ResetToAcceptingConnectionState();
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+
+  base::ProcessHandle handle2 = SpawnChild("IPCChannelPosixTestConnectionProc",
+                                          false);
+  ASSERT_TRUE(handle2);
+  SpinRunLoop(TestTimeouts::action_max_timeout_ms());
+  ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
+  ASSERT_TRUE(channel.HasAcceptedConnection());
+  IPC::Message* message = new IPC::Message(0, // routing_id
+                                           QUIT_MESSAGE, // message type
+                                           IPC::Message::PRIORITY_NORMAL);
+  channel.Send(message);
+  SpinRunLoop(TestTimeouts::action_timeout_ms());
+  EXPECT_TRUE(base::KillProcess(handle, 0, false));
+  int exit_code = 0;
+  EXPECT_TRUE(base::WaitForExitCode(handle2, &exit_code));
+  EXPECT_EQ(0, exit_code);
+  ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+}
+
+TEST_F(IPCChannelPosixTest, MultiConnection) {
+  // Test setting up a connection to an external process, and then have
+  // another external process attempt to connect to us.
+  IPCChannelPosixTestListener listener(false);
+  IPC::ChannelHandle chan_handle(kConnectionSocketTestName);
+  SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER);
+  IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
+  ASSERT_TRUE(channel.Connect());
+  ASSERT_TRUE(channel.AcceptsConnections());
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+
+  base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc",
+                                          false);
+  ASSERT_TRUE(handle);
+  SpinRunLoop(TestTimeouts::action_max_timeout_ms());
+  ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
+  ASSERT_TRUE(channel.HasAcceptedConnection());
+  base::ProcessHandle handle2 = SpawnChild("IPCChannelPosixFailConnectionProc",
+                                           false);
+  ASSERT_TRUE(handle2);
+  SpinRunLoop(TestTimeouts::action_max_timeout_ms());
+  int exit_code = 0;
+  EXPECT_TRUE(base::WaitForExitCode(handle2, &exit_code));
+  EXPECT_EQ(exit_code, 0);
+  ASSERT_EQ(IPCChannelPosixTestListener::DENIED, listener.status());
+  ASSERT_TRUE(channel.HasAcceptedConnection());
+  IPC::Message* message = new IPC::Message(0, // routing_id
+                                           QUIT_MESSAGE, // message type
+                                           IPC::Message::PRIORITY_NORMAL);
+  channel.Send(message);
+  SpinRunLoop(TestTimeouts::action_timeout_ms());
+  EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
+  EXPECT_EQ(exit_code, 0);
+  ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
+  ASSERT_FALSE(channel.HasAcceptedConnection());
+}
+
+TEST_F(IPCChannelPosixTest, DoubleServer) {
+  // Test setting up two servers with the same name.
+  IPCChannelPosixTestListener listener(false);
+  IPCChannelPosixTestListener listener2(false);
+  IPC::ChannelHandle chan_handle(kConnectionSocketTestName);
+  IPC::Channel channel(chan_handle, IPC::Channel::MODE_SERVER, &listener);
+  IPC::Channel channel2(chan_handle, IPC::Channel::MODE_SERVER, &listener2);
+  ASSERT_TRUE(channel.Connect());
+  ASSERT_FALSE(channel2.Connect());
+}
+
+TEST_F(IPCChannelPosixTest, BadMode) {
+  // Test setting up two servers with a bad mode.
+  IPCChannelPosixTestListener listener(false);
+  IPC::ChannelHandle chan_handle(kConnectionSocketTestName);
+  IPC::Channel channel(chan_handle, IPC::Channel::MODE_NONE, &listener);
+  ASSERT_FALSE(channel.Connect());
+}
+
+TEST_F(IPCChannelPosixTest, IsNamedServerInitialized) {
+  IPCChannelPosixTestListener listener(false);
+  IPC::ChannelHandle chan_handle(kConnectionSocketTestName);
+  ASSERT_TRUE(file_util::Delete(FilePath(kConnectionSocketTestName), false));
+  ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized(
+      kConnectionSocketTestName));
+  IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
+  ASSERT_TRUE(IPC::Channel::IsNamedServerInitialized(
+      kConnectionSocketTestName));
+  channel.Close();
+  ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized(
+      kConnectionSocketTestName));
+}
+
+// A long running process that connects to us
+MULTIPROCESS_TEST_MAIN(IPCChannelPosixTestConnectionProc) {
+  MessageLoopForIO message_loop;
+  IPCChannelPosixTestListener listener(true);
+  IPC::ChannelHandle handle(IPCChannelPosixTest::kConnectionSocketTestName);
+  IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT);
+  IPC::Channel channel(handle, IPC::Channel::MODE_NAMED_CLIENT, &listener);
+  EXPECT_TRUE(channel.Connect());
+  IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout_ms());
+  EXPECT_EQ(IPCChannelPosixTestListener::MESSAGE_RECEIVED, listener.status());
+  return 0;
+}
+
+// Simple external process that shouldn't be able to connect to us.
+MULTIPROCESS_TEST_MAIN(IPCChannelPosixFailConnectionProc) {
+  MessageLoopForIO message_loop;
+  IPCChannelPosixTestListener listener(false);
+  IPC::ChannelHandle handle(IPCChannelPosixTest::kConnectionSocketTestName);
+  IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT);
+  IPC::Channel channel(handle, IPC::Channel::MODE_NAMED_CLIENT, &listener);
+
+  // In this case connect may succeed or fail depending on if the packet
+  // actually gets sent at sendmsg. Since we never delay on send, we may not
+  // see the error. However even if connect succeeds, eventually we will get an
+  // error back since the channel will be closed when we attempt to read from
+  // it.
+  bool connected = channel.Connect();
+  if (connected) {
+    IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout_ms());
+    EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
+  } else {
+    EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status());
+  }
+  return 0;
+}
+
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc
new file mode 100644 (file)
index 0000000..dc990c2
--- /dev/null
@@ -0,0 +1,397 @@
+// 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 "base/memory/scoped_ptr.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace IPC {
+
+//------------------------------------------------------------------------------
+
+// This task ensures the message is deleted if the task is deleted without
+// having been run.
+class SendTask : public Task {
+ public:
+  SendTask(ChannelProxy::Context* context, Message* message)
+      : context_(context),
+        message_(message) {
+  }
+
+  virtual void Run() {
+    context_->OnSendMessage(message_.release());
+  }
+
+ private:
+  scoped_refptr<ChannelProxy::Context> context_;
+  scoped_ptr<Message> message_;
+
+  DISALLOW_COPY_AND_ASSIGN(SendTask);
+};
+
+//------------------------------------------------------------------------------
+
+ChannelProxy::MessageFilter::MessageFilter() {}
+
+ChannelProxy::MessageFilter::~MessageFilter() {}
+
+void ChannelProxy::MessageFilter::OnFilterAdded(Channel* channel) {}
+
+void ChannelProxy::MessageFilter::OnFilterRemoved() {}
+
+void ChannelProxy::MessageFilter::OnChannelConnected(int32 peer_pid) {}
+
+void ChannelProxy::MessageFilter::OnChannelError() {}
+
+void ChannelProxy::MessageFilter::OnChannelClosing() {}
+
+bool ChannelProxy::MessageFilter::OnMessageReceived(const Message& message) {
+  return false;
+}
+
+void ChannelProxy::MessageFilter::OnDestruct() const {
+  delete this;
+}
+
+//------------------------------------------------------------------------------
+
+ChannelProxy::Context::Context(Channel::Listener* listener,
+                               base::MessageLoopProxy* ipc_message_loop)
+    : listener_message_loop_(base::MessageLoopProxy::current()),
+      listener_(listener),
+      ipc_message_loop_(ipc_message_loop),
+      peer_pid_(0),
+      channel_connected_called_(false) {
+}
+
+ChannelProxy::Context::~Context() {
+}
+
+void ChannelProxy::Context::CreateChannel(const IPC::ChannelHandle& handle,
+                                          const Channel::Mode& mode) {
+  DCHECK(channel_.get() == NULL);
+  channel_id_ = handle.name;
+  channel_.reset(new Channel(handle, mode, this));
+}
+
+bool ChannelProxy::Context::TryFilters(const Message& message) {
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  Logging* logger = Logging::GetInstance();
+  if (logger->Enabled())
+    logger->OnPreDispatchMessage(message);
+#endif
+
+  for (size_t i = 0; i < filters_.size(); ++i) {
+    if (filters_[i]->OnMessageReceived(message)) {
+#ifdef IPC_MESSAGE_LOG_ENABLED
+      if (logger->Enabled())
+        logger->OnPostDispatchMessage(message, channel_id_);
+#endif
+      return true;
+    }
+  }
+  return false;
+}
+
+// Called on the IPC::Channel thread
+bool ChannelProxy::Context::OnMessageReceived(const Message& message) {
+  // First give a chance to the filters to process this message.
+  if (!TryFilters(message))
+    OnMessageReceivedNoFilter(message);
+  return true;
+}
+
+// Called on the IPC::Channel thread
+bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
+  // NOTE: This code relies on the listener's message loop not going away while
+  // this thread is active.  That should be a reasonable assumption, but it
+  // feels risky.  We may want to invent some more indirect way of referring to
+  // a MessageLoop if this becomes a problem.
+  listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &Context::OnDispatchMessage, message));
+  return true;
+}
+
+// Called on the IPC::Channel thread
+void ChannelProxy::Context::OnChannelConnected(int32 peer_pid) {
+  // Add any pending filters.  This avoids a race condition where someone
+  // creates a ChannelProxy, calls AddFilter, and then right after starts the
+  // peer process.  The IO thread could receive a message before the task to add
+  // the filter is run on the IO thread.
+  OnAddFilter();
+
+  peer_pid_ = peer_pid;
+  for (size_t i = 0; i < filters_.size(); ++i)
+    filters_[i]->OnChannelConnected(peer_pid);
+
+  // See above comment about using listener_message_loop_ here.
+  listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &Context::OnDispatchConnected));
+}
+
+// Called on the IPC::Channel thread
+void ChannelProxy::Context::OnChannelError() {
+  for (size_t i = 0; i < filters_.size(); ++i)
+    filters_[i]->OnChannelError();
+
+  // See above comment about using listener_message_loop_ here.
+  listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &Context::OnDispatchError));
+}
+
+// Called on the IPC::Channel thread
+void ChannelProxy::Context::OnChannelOpened() {
+  DCHECK(channel_ != NULL);
+
+  // Assume a reference to ourselves on behalf of this thread.  This reference
+  // will be released when we are closed.
+  AddRef();
+
+  if (!channel_->Connect()) {
+    OnChannelError();
+    return;
+  }
+
+  for (size_t i = 0; i < filters_.size(); ++i)
+    filters_[i]->OnFilterAdded(channel_.get());
+}
+
+// Called on the IPC::Channel thread
+void ChannelProxy::Context::OnChannelClosed() {
+  // It's okay for IPC::ChannelProxy::Close to be called more than once, which
+  // would result in this branch being taken.
+  if (!channel_.get())
+    return;
+
+  for (size_t i = 0; i < filters_.size(); ++i) {
+    filters_[i]->OnChannelClosing();
+    filters_[i]->OnFilterRemoved();
+  }
+
+  // We don't need the filters anymore.
+  filters_.clear();
+
+  channel_.reset();
+
+  // Balance with the reference taken during startup.  This may result in
+  // self-destruction.
+  Release();
+}
+
+// Called on the IPC::Channel thread
+void ChannelProxy::Context::OnSendMessage(Message* message) {
+  if (!channel_.get()) {
+    delete message;
+    OnChannelClosed();
+    return;
+  }
+  if (!channel_->Send(message))
+    OnChannelError();
+}
+
+// Called on the IPC::Channel thread
+void ChannelProxy::Context::OnAddFilter() {
+  std::vector<scoped_refptr<MessageFilter> > new_filters;
+  {
+    base::AutoLock auto_lock(pending_filters_lock_);
+    new_filters.swap(pending_filters_);
+  }
+
+  for (size_t i = 0; i < new_filters.size(); ++i) {
+    filters_.push_back(new_filters[i]);
+
+    // If the channel has already been created, then we need to send this
+    // message so that the filter gets access to the Channel.
+    if (channel_.get())
+      new_filters[i]->OnFilterAdded(channel_.get());
+    // Ditto for if the channel has been connected.
+    if (peer_pid_)
+      new_filters[i]->OnChannelConnected(peer_pid_);
+  }
+}
+
+// Called on the IPC::Channel thread
+void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) {
+  for (size_t i = 0; i < filters_.size(); ++i) {
+    if (filters_[i].get() == filter) {
+      filter->OnFilterRemoved();
+      filters_.erase(filters_.begin() + i);
+      return;
+    }
+  }
+
+  NOTREACHED() << "filter to be removed not found";
+}
+
+// Called on the listener's thread
+void ChannelProxy::Context::AddFilter(MessageFilter* filter) {
+  base::AutoLock auto_lock(pending_filters_lock_);
+  pending_filters_.push_back(make_scoped_refptr(filter));
+  ipc_message_loop_->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this, &Context::OnAddFilter));
+}
+
+// Called on the listener's thread
+void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
+  if (!listener_)
+    return;
+
+  OnDispatchConnected();
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  Logging* logger = Logging::GetInstance();
+  if (message.type() == IPC_LOGGING_ID) {
+    logger->OnReceivedLoggingMessage(message);
+    return;
+  }
+
+  if (logger->Enabled())
+    logger->OnPreDispatchMessage(message);
+#endif
+
+  listener_->OnMessageReceived(message);
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  if (logger->Enabled())
+    logger->OnPostDispatchMessage(message, channel_id_);
+#endif
+}
+
+// Called on the listener's thread
+void ChannelProxy::Context::OnDispatchConnected() {
+  if (channel_connected_called_)
+    return;
+
+  channel_connected_called_ = true;
+  if (listener_)
+    listener_->OnChannelConnected(peer_pid_);
+}
+
+// Called on the listener's thread
+void ChannelProxy::Context::OnDispatchError() {
+  if (listener_)
+    listener_->OnChannelError();
+}
+
+//-----------------------------------------------------------------------------
+
+ChannelProxy::ChannelProxy(const IPC::ChannelHandle& channel_handle,
+                           Channel::Mode mode,
+                           Channel::Listener* listener,
+                           base::MessageLoopProxy* ipc_thread)
+    : context_(new Context(listener, ipc_thread)),
+      outgoing_message_filter_(NULL) {
+  Init(channel_handle, mode, ipc_thread, true);
+}
+
+ChannelProxy::ChannelProxy(const IPC::ChannelHandle& channel_handle,
+                           Channel::Mode mode,
+                           base::MessageLoopProxy* ipc_thread,
+                           Context* context,
+                           bool create_pipe_now)
+    : context_(context),
+      outgoing_message_filter_(NULL) {
+  Init(channel_handle, mode, ipc_thread, create_pipe_now);
+}
+
+ChannelProxy::~ChannelProxy() {
+  Close();
+}
+
+void ChannelProxy::Init(const IPC::ChannelHandle& channel_handle,
+                        Channel::Mode mode,
+                        base::MessageLoopProxy* ipc_thread_loop,
+                        bool create_pipe_now) {
+#if defined(OS_POSIX)
+  // When we are creating a server on POSIX, we need its file descriptor
+  // to be created immediately so that it can be accessed and passed
+  // to other processes. Forcing it to be created immediately avoids
+  // race conditions that may otherwise arise.
+  if (mode & Channel::MODE_SERVER_FLAG) {
+    create_pipe_now = true;
+  }
+#endif  // defined(OS_POSIX)
+
+  if (create_pipe_now) {
+    // Create the channel immediately.  This effectively sets up the
+    // low-level pipe so that the client can connect.  Without creating
+    // the pipe immediately, it is possible for a listener to attempt
+    // to connect and get an error since the pipe doesn't exist yet.
+    context_->CreateChannel(channel_handle, mode);
+  } else {
+    context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+        context_.get(), &Context::CreateChannel, channel_handle, mode));
+  }
+
+  // complete initialization on the background thread
+  context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+      context_.get(), &Context::OnChannelOpened));
+}
+
+void ChannelProxy::Close() {
+  // Clear the backpointer to the listener so that any pending calls to
+  // Context::OnDispatchMessage or OnDispatchError will be ignored.  It is
+  // possible that the channel could be closed while it is receiving messages!
+  context_->Clear();
+
+  if (context_->ipc_message_loop()) {
+    context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+        context_.get(), &Context::OnChannelClosed));
+  }
+}
+
+bool ChannelProxy::Send(Message* message) {
+  if (outgoing_message_filter())
+    message = outgoing_message_filter()->Rewrite(message);
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  Logging::GetInstance()->OnSendMessage(message, context_->channel_id());
+#endif
+
+  context_->ipc_message_loop()->PostTask(FROM_HERE,
+                                         new SendTask(context_.get(), message));
+  return true;
+}
+
+void ChannelProxy::AddFilter(MessageFilter* filter) {
+  context_->AddFilter(filter);
+}
+
+void ChannelProxy::RemoveFilter(MessageFilter* filter) {
+  context_->ipc_message_loop()->PostTask(
+      FROM_HERE, NewRunnableMethod(
+          context_.get(),
+          &Context::OnRemoveFilter,
+          make_scoped_refptr(filter)));
+}
+
+void ChannelProxy::ClearIPCMessageLoop() {
+  context()->ClearIPCMessageLoop();
+}
+
+#if defined(OS_POSIX) && !defined(OS_NACL)
+// See the TODO regarding lazy initialization of the channel in
+// ChannelProxy::Init().
+// We assume that IPC::Channel::GetClientFileDescriptorMapping() is thread-safe.
+int ChannelProxy::GetClientFileDescriptor() const {
+  Channel *channel = context_.get()->channel_.get();
+  // Channel must have been created first.
+  DCHECK(channel) << context_.get()->channel_id_;
+  return channel->GetClientFileDescriptor();
+}
+
+bool ChannelProxy::GetClientEuid(uid_t* client_euid) const {
+  Channel *channel = context_.get()->channel_.get();
+  // Channel must have been created first.
+  DCHECK(channel) << context_.get()->channel_id_;
+  return channel->GetClientEuid(client_euid);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+}  // namespace IPC
diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h
new file mode 100644 (file)
index 0000000..792e3d6
--- /dev/null
@@ -0,0 +1,272 @@
+// 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 IPC_IPC_CHANNEL_PROXY_H_
+#define IPC_IPC_CHANNEL_PROXY_H_
+#pragma once
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop_proxy.h"
+#include "base/synchronization/lock.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_handle.h"
+
+namespace IPC {
+
+class SendTask;
+
+//-----------------------------------------------------------------------------
+// IPC::ChannelProxy
+//
+// This class is a helper class that is useful when you wish to run an IPC
+// channel on a background thread.  It provides you with the option of either
+// handling IPC messages on that background thread or having them dispatched to
+// your main thread (the thread on which the IPC::ChannelProxy is created).
+//
+// The API for an IPC::ChannelProxy is very similar to that of an IPC::Channel.
+// When you send a message to an IPC::ChannelProxy, the message is routed to
+// the background thread, where it is then passed to the IPC::Channel's Send
+// method.  This means that you can send a message from your thread and your
+// message will be sent over the IPC channel when possible instead of being
+// delayed until your thread returns to its message loop.  (Often IPC messages
+// will queue up on the IPC::Channel when there is a lot of traffic, and the
+// channel will not get cycles to flush its message queue until the thread, on
+// which it is running, returns to its message loop.)
+//
+// An IPC::ChannelProxy can have a MessageFilter associated with it, which will
+// be notified of incoming messages on the IPC::Channel's thread.  This gives
+// the consumer of IPC::ChannelProxy the ability to respond to incoming
+// messages on this background thread instead of on their own thread, which may
+// be bogged down with other processing.  The result can be greatly improved
+// latency for messages that can be handled on a background thread.
+//
+// The consumer of IPC::ChannelProxy is responsible for allocating the Thread
+// instance where the IPC::Channel will be created and operated.
+//
+class IPC_EXPORT ChannelProxy : public Message::Sender {
+ public:
+
+  struct MessageFilterTraits;
+
+  // A class that receives messages on the thread where the IPC channel is
+  // running.  It can choose to prevent the default action for an IPC message.
+  class IPC_EXPORT MessageFilter
+      : public base::RefCountedThreadSafe<MessageFilter, MessageFilterTraits> {
+   public:
+    MessageFilter();
+    virtual ~MessageFilter();
+
+    // Called on the background thread to provide the filter with access to the
+    // channel.  Called when the IPC channel is initialized or when AddFilter
+    // is called if the channel is already initialized.
+    virtual void OnFilterAdded(Channel* channel);
+
+    // Called on the background thread when the filter has been removed from
+    // the ChannelProxy and when the Channel is closing.  After a filter is
+    // removed, it will not be called again.
+    virtual void OnFilterRemoved();
+
+    // Called to inform the filter that the IPC channel is connected and we
+    // have received the internal Hello message from the peer.
+    virtual void OnChannelConnected(int32 peer_pid);
+
+    // Called when there is an error on the channel, typically that the channel
+    // has been closed.
+    virtual void OnChannelError();
+
+    // Called to inform the filter that the IPC channel will be destroyed.
+    // OnFilterRemoved is called immediately after this.
+    virtual void OnChannelClosing();
+
+    // Return true to indicate that the message was handled, or false to let
+    // the message be handled in the default way.
+    virtual bool OnMessageReceived(const Message& message);
+
+    // Called when the message filter is about to be deleted.  This gives
+    // derived classes the option of controlling which thread they're deleted
+    // on etc.
+    virtual void OnDestruct() const;
+  };
+
+  struct MessageFilterTraits {
+    static void Destruct(const MessageFilter* filter) {
+      filter->OnDestruct();
+    }
+  };
+
+  // Interface for a filter to be imposed on outgoing messages which can
+  // re-write the message.  Used mainly for testing.
+  class OutgoingMessageFilter {
+   public:
+    // Returns a re-written message, freeing the original, or simply the
+    // original unchanged if no rewrite indicated.
+    virtual Message *Rewrite(Message *message) = 0;
+  };
+
+  // Initializes a channel proxy.  The channel_handle and mode parameters are
+  // passed directly to the underlying IPC::Channel.  The listener is called on
+  // the thread that creates the ChannelProxy.  The filter's OnMessageReceived
+  // method is called on the thread where the IPC::Channel is running.  The
+  // filter may be null if the consumer is not interested in handling messages
+  // on the background thread.  Any message not handled by the filter will be
+  // dispatched to the listener.  The given message loop indicates where the
+  // IPC::Channel should be created.
+  ChannelProxy(const IPC::ChannelHandle& channel_handle,
+               Channel::Mode mode,
+               Channel::Listener* listener,
+               base::MessageLoopProxy* ipc_thread_loop);
+
+  virtual ~ChannelProxy();
+
+  // Close the IPC::Channel.  This operation completes asynchronously, once the
+  // background thread processes the command to close the channel.  It is ok to
+  // call this method multiple times.  Redundant calls are ignored.
+  //
+  // WARNING: The MessageFilter object held by the ChannelProxy is also
+  // released asynchronously, and it may in fact have its final reference
+  // released on the background thread.  The caller should be careful to deal
+  // with / allow for this possibility.
+  void Close();
+
+  // Send a message asynchronously.  The message is routed to the background
+  // thread where it is passed to the IPC::Channel's Send method.
+  virtual bool Send(Message* message);
+
+  // Used to intercept messages as they are received on the background thread.
+  //
+  // Ordinarily, messages sent to the ChannelProxy are routed to the matching
+  // listener on the worker thread.  This API allows code to intercept messages
+  // before they are sent to the worker thread.
+  // If you call this before the target process is launched, then you're
+  // guaranteed to not miss any messages.  But if you call this anytime after,
+  // then some messages might be missed since the filter is added internally on
+  // the IO thread.
+  void AddFilter(MessageFilter* filter);
+  void RemoveFilter(MessageFilter* filter);
+
+  void set_outgoing_message_filter(OutgoingMessageFilter* filter) {
+    outgoing_message_filter_ = filter;
+  }
+
+  // Called to clear the pointer to the IPC message loop when it's going away.
+  void ClearIPCMessageLoop();
+
+#if defined(OS_POSIX)
+  // Calls through to the underlying channel's methods.
+  int GetClientFileDescriptor() const;
+  bool GetClientEuid(uid_t* client_euid) const;
+#endif  // defined(OS_POSIX)
+
+ protected:
+  class Context;
+  // A subclass uses this constructor if it needs to add more information
+  // to the internal state.  If create_pipe_now is true, the pipe is created
+  // immediately.  Otherwise it's created on the IO thread.
+  ChannelProxy(const IPC::ChannelHandle& channel_handle,
+               Channel::Mode mode,
+               base::MessageLoopProxy* ipc_thread_loop,
+               Context* context,
+               bool create_pipe_now);
+
+  // Used internally to hold state that is referenced on the IPC thread.
+  class Context : public base::RefCountedThreadSafe<Context>,
+                  public Channel::Listener {
+   public:
+    Context(Channel::Listener* listener, base::MessageLoopProxy* ipc_thread);
+    void ClearIPCMessageLoop() { ipc_message_loop_ = NULL; }
+    base::MessageLoopProxy* ipc_message_loop() const {
+      return ipc_message_loop_.get();
+    }
+    const std::string& channel_id() const { return channel_id_; }
+
+    // Dispatches a message on the listener thread.
+    void OnDispatchMessage(const Message& message);
+
+   protected:
+    friend class base::RefCountedThreadSafe<Context>;
+    virtual ~Context();
+
+    // IPC::Channel::Listener methods:
+    virtual bool OnMessageReceived(const Message& message) OVERRIDE;
+    virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+    virtual void OnChannelError() OVERRIDE;
+
+    // Like OnMessageReceived but doesn't try the filters.
+    bool OnMessageReceivedNoFilter(const Message& message);
+
+    // Gives the filters a chance at processing |message|.
+    // Returns true if the message was processed, false otherwise.
+    bool TryFilters(const Message& message);
+
+    // Like Open and Close, but called on the IPC thread.
+    virtual void OnChannelOpened();
+    virtual void OnChannelClosed();
+
+    // Called on the consumers thread when the ChannelProxy is closed.  At that
+    // point the consumer is telling us that they don't want to receive any
+    // more messages, so we honor that wish by forgetting them!
+    virtual void Clear() { listener_ = NULL; }
+
+   private:
+    friend class ChannelProxy;
+    friend class SendTask;
+
+    // Create the Channel
+    void CreateChannel(const IPC::ChannelHandle& channel_handle,
+                       const Channel::Mode& mode);
+
+    // Methods called on the IO thread.
+    void OnSendMessage(Message* message_ptr);
+    void OnAddFilter();
+    void OnRemoveFilter(MessageFilter* filter);
+
+    // Methods called on the listener thread.
+    void AddFilter(MessageFilter* filter);
+    void OnDispatchConnected();
+    void OnDispatchError();
+
+    scoped_refptr<base::MessageLoopProxy> listener_message_loop_;
+    Channel::Listener* listener_;
+
+    // List of filters.  This is only accessed on the IPC thread.
+    std::vector<scoped_refptr<MessageFilter> > filters_;
+    scoped_refptr<base::MessageLoopProxy> ipc_message_loop_;
+    scoped_ptr<Channel> channel_;
+    std::string channel_id_;
+    int peer_pid_;
+    bool channel_connected_called_;
+
+    // Holds filters between the AddFilter call on the listerner thread and the
+    // IPC thread when they're added to filters_.
+    std::vector<scoped_refptr<MessageFilter> > pending_filters_;
+    // Lock for pending_filters_.
+    base::Lock pending_filters_lock_;
+  };
+
+  Context* context() { return context_; }
+
+  OutgoingMessageFilter* outgoing_message_filter() {
+    return outgoing_message_filter_;
+  }
+
+ private:
+  friend class SendTask;
+
+  void Init(const IPC::ChannelHandle& channel_handle, Channel::Mode mode,
+            base::MessageLoopProxy* ipc_thread_loop, bool create_pipe_now);
+
+  // By maintaining this indirection (ref-counted) to our internal state, we
+  // can safely be destroyed while the background thread continues to do stuff
+  // that involves this data.
+  scoped_refptr<Context> context_;
+
+  OutgoingMessageFilter* outgoing_message_filter_;
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_CHANNEL_PROXY_H_
diff --git a/ipc/ipc_channel_win.cc b/ipc/ipc_channel_win.cc
new file mode 100644 (file)
index 0000000..3a85a16
--- /dev/null
@@ -0,0 +1,430 @@
+// 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 "ipc/ipc_channel_win.h"
+
+#include <windows.h>
+
+#include "base/auto_reset.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/utf_string_conversions.h"
+#include "base/win/scoped_handle.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace IPC {
+
+Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) {
+  memset(&context.overlapped, 0, sizeof(context.overlapped));
+  context.handler = channel;
+}
+
+Channel::ChannelImpl::State::~State() {
+  COMPILE_ASSERT(!offsetof(Channel::ChannelImpl::State, context),
+                 starts_with_io_context);
+}
+
+Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle &channel_handle,
+                                  Mode mode, Listener* listener)
+    : ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)),
+      ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)),
+      pipe_(INVALID_HANDLE_VALUE),
+      listener_(listener),
+      waiting_connect_(mode & MODE_SERVER_FLAG),
+      processing_incoming_(false),
+      ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
+  CreatePipe(channel_handle, mode);
+}
+
+Channel::ChannelImpl::~ChannelImpl() {
+  Close();
+}
+
+void Channel::ChannelImpl::Close() {
+  if (thread_check_.get()) {
+    DCHECK(thread_check_->CalledOnValidThread());
+  }
+
+  if (input_state_.is_pending || output_state_.is_pending)
+    CancelIo(pipe_);
+
+  // Closing the handle at this point prevents us from issuing more requests
+  // form OnIOCompleted().
+  if (pipe_ != INVALID_HANDLE_VALUE) {
+    CloseHandle(pipe_);
+    pipe_ = INVALID_HANDLE_VALUE;
+  }
+
+  // Make sure all IO has completed.
+  base::Time start = base::Time::Now();
+  while (input_state_.is_pending || output_state_.is_pending) {
+    MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this);
+  }
+
+  while (!output_queue_.empty()) {
+    Message* m = output_queue_.front();
+    output_queue_.pop();
+    delete m;
+  }
+}
+
+bool Channel::ChannelImpl::Send(Message* message) {
+  DCHECK(thread_check_->CalledOnValidThread());
+  DVLOG(2) << "sending message @" << message << " on channel @" << this
+           << " with type " << message->type()
+           << " (" << output_queue_.size() << " in queue)";
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  Logging::GetInstance()->OnSendMessage(message, "");
+#endif
+
+  output_queue_.push(message);
+  // ensure waiting to write
+  if (!waiting_connect_) {
+    if (!output_state_.is_pending) {
+      if (!ProcessOutgoingMessages(NULL, 0))
+        return false;
+    }
+  }
+
+  return true;
+}
+
+// static
+bool Channel::ChannelImpl::IsNamedServerInitialized(
+    const std::string& channel_id) {
+  if (WaitNamedPipe(PipeName(channel_id).c_str(), 1))
+    return true;
+  // If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another
+  // connection.
+  return GetLastError() == ERROR_SEM_TIMEOUT;
+}
+
+// static
+const std::wstring Channel::ChannelImpl::PipeName(
+    const std::string& channel_id) {
+  std::string name("\\\\.\\pipe\\chrome.");
+  return ASCIIToWide(name.append(channel_id));
+}
+
+bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle,
+                                      Mode mode) {
+  DCHECK_EQ(INVALID_HANDLE_VALUE, pipe_);
+  const std::wstring pipe_name = PipeName(channel_handle.name);
+  if (mode & MODE_SERVER_FLAG) {
+    pipe_ = CreateNamedPipeW(pipe_name.c_str(),
+                             PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
+                              FILE_FLAG_FIRST_PIPE_INSTANCE,
+                             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
+                             1,
+                             Channel::kReadBufferSize,
+                             Channel::kReadBufferSize,
+                             5000,
+                             NULL);
+  } else if (mode & MODE_CLIENT_FLAG) {
+    pipe_ = CreateFileW(pipe_name.c_str(),
+                        GENERIC_READ | GENERIC_WRITE,
+                        0,
+                        NULL,
+                        OPEN_EXISTING,
+                        SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
+                            FILE_FLAG_OVERLAPPED,
+                        NULL);
+  } else {
+    NOTREACHED();
+  }
+  if (pipe_ == INVALID_HANDLE_VALUE) {
+    // If this process is being closed, the pipe may be gone already.
+    LOG(WARNING) << "Unable to create pipe \"" << pipe_name <<
+                    "\" in " << (mode == 0 ? "server" : "client")
+                    << " mode. Error :" << GetLastError();
+    return false;
+  }
+
+  // Create the Hello message to be sent when Connect is called
+  scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE,
+                                    HELLO_MESSAGE_TYPE,
+                                    IPC::Message::PRIORITY_NORMAL));
+  if (!m->WriteInt(GetCurrentProcessId())) {
+    CloseHandle(pipe_);
+    pipe_ = INVALID_HANDLE_VALUE;
+    return false;
+  }
+
+  output_queue_.push(m.release());
+  return true;
+}
+
+bool Channel::ChannelImpl::Connect() {
+  DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once";
+
+  if (!thread_check_.get())
+    thread_check_.reset(new base::NonThreadSafe());
+
+  if (pipe_ == INVALID_HANDLE_VALUE)
+    return false;
+
+  MessageLoopForIO::current()->RegisterIOHandler(pipe_, this);
+
+  // Check to see if there is a client connected to our pipe...
+  if (waiting_connect_)
+    ProcessConnection();
+
+  if (!input_state_.is_pending) {
+    // Complete setup asynchronously. By not setting input_state_.is_pending
+    // to true, we indicate to OnIOCompleted that this is the special
+    // initialization signal.
+    MessageLoopForIO::current()->PostTask(FROM_HERE, factory_.NewRunnableMethod(
+        &Channel::ChannelImpl::OnIOCompleted, &input_state_.context, 0, 0));
+  }
+
+  if (!waiting_connect_)
+    ProcessOutgoingMessages(NULL, 0);
+  return true;
+}
+
+bool Channel::ChannelImpl::ProcessConnection() {
+  DCHECK(thread_check_->CalledOnValidThread());
+  if (input_state_.is_pending)
+    input_state_.is_pending = false;
+
+  // Do we have a client connected to our pipe?
+  if (INVALID_HANDLE_VALUE == pipe_)
+    return false;
+
+  BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped);
+
+  DWORD err = GetLastError();
+  if (ok) {
+    // Uhm, the API documentation says that this function should never
+    // return success when used in overlapped mode.
+    NOTREACHED();
+    return false;
+  }
+
+  switch (err) {
+  case ERROR_IO_PENDING:
+    input_state_.is_pending = true;
+    break;
+  case ERROR_PIPE_CONNECTED:
+    waiting_connect_ = false;
+    break;
+  case ERROR_NO_DATA:
+    // The pipe is being closed.
+    return false;
+  default:
+    NOTREACHED();
+    return false;
+  }
+
+  return true;
+}
+
+bool Channel::ChannelImpl::ProcessIncomingMessages(
+    MessageLoopForIO::IOContext* context,
+    DWORD bytes_read) {
+  DCHECK(thread_check_->CalledOnValidThread());
+  if (input_state_.is_pending) {
+    input_state_.is_pending = false;
+    DCHECK(context);
+
+    if (!context || !bytes_read)
+      return false;
+  } else {
+    // This happens at channel initialization.
+    DCHECK(!bytes_read && context == &input_state_.context);
+  }
+
+  for (;;) {
+    if (bytes_read == 0) {
+      if (INVALID_HANDLE_VALUE == pipe_)
+        return false;
+
+      // Read from pipe...
+      BOOL ok = ReadFile(pipe_,
+                         input_buf_,
+                         Channel::kReadBufferSize,
+                         &bytes_read,
+                         &input_state_.context.overlapped);
+      if (!ok) {
+        DWORD err = GetLastError();
+        if (err == ERROR_IO_PENDING) {
+          input_state_.is_pending = true;
+          return true;
+        }
+        LOG(ERROR) << "pipe error: " << err;
+        return false;
+      }
+      input_state_.is_pending = true;
+      return true;
+    }
+    DCHECK(bytes_read);
+
+    // Process messages from input buffer.
+
+    const char* p, *end;
+    if (input_overflow_buf_.empty()) {
+      p = input_buf_;
+      end = p + bytes_read;
+    } else {
+      if (input_overflow_buf_.size() > (kMaximumMessageSize - bytes_read)) {
+        input_overflow_buf_.clear();
+        LOG(ERROR) << "IPC message is too big";
+        return false;
+      }
+      input_overflow_buf_.append(input_buf_, bytes_read);
+      p = input_overflow_buf_.data();
+      end = p + input_overflow_buf_.size();
+    }
+
+    while (p < end) {
+      const char* message_tail = Message::FindNext(p, end);
+      if (message_tail) {
+        int len = static_cast<int>(message_tail - p);
+        const Message m(p, len);
+        DVLOG(2) << "received message on channel @" << this
+                 << " with type " << m.type();
+        if (m.routing_id() == MSG_ROUTING_NONE &&
+            m.type() == HELLO_MESSAGE_TYPE) {
+          // The Hello message contains only the process id.
+          listener_->OnChannelConnected(MessageIterator(m).NextInt());
+        } else {
+          listener_->OnMessageReceived(m);
+        }
+        p = message_tail;
+      } else {
+        // Last message is partial.
+        break;
+      }
+    }
+    input_overflow_buf_.assign(p, end - p);
+
+    bytes_read = 0;  // Get more data.
+  }
+
+  return true;
+}
+
+bool Channel::ChannelImpl::ProcessOutgoingMessages(
+    MessageLoopForIO::IOContext* context,
+    DWORD bytes_written) {
+  DCHECK(!waiting_connect_);  // Why are we trying to send messages if there's
+                              // no connection?
+  DCHECK(thread_check_->CalledOnValidThread());
+
+  if (output_state_.is_pending) {
+    DCHECK(context);
+    output_state_.is_pending = false;
+    if (!context || bytes_written == 0) {
+      DWORD err = GetLastError();
+      LOG(ERROR) << "pipe error: " << err;
+      return false;
+    }
+    // Message was sent.
+    DCHECK(!output_queue_.empty());
+    Message* m = output_queue_.front();
+    output_queue_.pop();
+    delete m;
+  }
+
+  if (output_queue_.empty())
+    return true;
+
+  if (INVALID_HANDLE_VALUE == pipe_)
+    return false;
+
+  // Write to pipe...
+  Message* m = output_queue_.front();
+  DCHECK(m->size() <= INT_MAX);
+  BOOL ok = WriteFile(pipe_,
+                      m->data(),
+                      static_cast<int>(m->size()),
+                      &bytes_written,
+                      &output_state_.context.overlapped);
+  if (!ok) {
+    DWORD err = GetLastError();
+    if (err == ERROR_IO_PENDING) {
+      output_state_.is_pending = true;
+
+      DVLOG(2) << "sent pending message @" << m << " on channel @" << this
+               << " with type " << m->type();
+
+      return true;
+    }
+    LOG(ERROR) << "pipe error: " << err;
+    return false;
+  }
+
+  DVLOG(2) << "sent message @" << m << " on channel @" << this
+           << " with type " << m->type();
+
+  output_state_.is_pending = true;
+  return true;
+}
+
+void Channel::ChannelImpl::OnIOCompleted(MessageLoopForIO::IOContext* context,
+                            DWORD bytes_transfered, DWORD error) {
+  bool ok;
+  DCHECK(thread_check_->CalledOnValidThread());
+  if (context == &input_state_.context) {
+    if (waiting_connect_) {
+      if (!ProcessConnection())
+        return;
+      // We may have some messages queued up to send...
+      if (!output_queue_.empty() && !output_state_.is_pending)
+        ProcessOutgoingMessages(NULL, 0);
+      if (input_state_.is_pending)
+        return;
+      // else, fall-through and look for incoming messages...
+    }
+    // we don't support recursion through OnMessageReceived yet!
+    DCHECK(!processing_incoming_);
+    AutoReset<bool> auto_reset_processing_incoming(&processing_incoming_, true);
+    ok = ProcessIncomingMessages(context, bytes_transfered);
+  } else {
+    DCHECK(context == &output_state_.context);
+    ok = ProcessOutgoingMessages(context, bytes_transfered);
+  }
+  if (!ok && INVALID_HANDLE_VALUE != pipe_) {
+    // We don't want to re-enter Close().
+    Close();
+    listener_->OnChannelError();
+  }
+}
+
+//------------------------------------------------------------------------------
+// Channel's methods simply call through to ChannelImpl.
+Channel::Channel(const IPC::ChannelHandle &channel_handle, Mode mode,
+                 Listener* listener)
+    : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) {
+}
+
+Channel::~Channel() {
+  delete channel_impl_;
+}
+
+bool Channel::Connect() {
+  return channel_impl_->Connect();
+}
+
+void Channel::Close() {
+  channel_impl_->Close();
+}
+
+void Channel::set_listener(Listener* listener) {
+  channel_impl_->set_listener(listener);
+}
+
+bool Channel::Send(Message* message) {
+  return channel_impl_->Send(message);
+}
+
+// static
+bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
+  return ChannelImpl::IsNamedServerInitialized(channel_id);
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_channel_win.h b/ipc/ipc_channel_win.h
new file mode 100644 (file)
index 0000000..ada88ac
--- /dev/null
@@ -0,0 +1,91 @@
+// 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 IPC_IPC_CHANNEL_WIN_H_
+#define IPC_IPC_CHANNEL_WIN_H_
+#pragma once
+
+#include "ipc/ipc_channel.h"
+
+#include <queue>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+
+namespace base {
+class NonThreadSafe;
+}
+
+namespace IPC {
+
+class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
+ public:
+  // Mirror methods of Channel, see ipc_channel.h for description.
+  ChannelImpl(const IPC::ChannelHandle &channel_handle, Mode mode,
+              Listener* listener);
+  ~ChannelImpl();
+  bool Connect();
+  void Close();
+  void set_listener(Listener* listener) { listener_ = listener; }
+  bool Send(Message* message);
+  static bool IsNamedServerInitialized(const std::string& channel_id);
+ private:
+  static const std::wstring PipeName(const std::string& channel_id);
+  bool CreatePipe(const IPC::ChannelHandle &channel_handle, Mode mode);
+
+  bool ProcessConnection();
+  bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context,
+                               DWORD bytes_read);
+  bool ProcessOutgoingMessages(MessageLoopForIO::IOContext* context,
+                               DWORD bytes_written);
+
+  // MessageLoop::IOHandler implementation.
+  virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
+                             DWORD bytes_transfered, DWORD error);
+ private:
+  struct State {
+    explicit State(ChannelImpl* channel);
+    ~State();
+    MessageLoopForIO::IOContext context;
+    bool is_pending;
+  };
+
+  State input_state_;
+  State output_state_;
+
+  HANDLE pipe_;
+
+  Listener* listener_;
+
+  // Messages to be sent are queued here.
+  std::queue<Message*> output_queue_;
+
+  // We read from the pipe into this buffer
+  char input_buf_[Channel::kReadBufferSize];
+
+  // Large messages that span multiple pipe buffers, get built-up using
+  // this buffer.
+  std::string input_overflow_buf_;
+
+  // In server-mode, we have to wait for the client to connect before we
+  // can begin reading.  We make use of the input_state_ when performing
+  // the connect operation in overlapped mode.
+  bool waiting_connect_;
+
+  // This flag is set when processing incoming messages.  It is used to
+  // avoid recursing through ProcessIncomingMessages, which could cause
+  // problems.  TODO(darin): make this unnecessary
+  bool processing_incoming_;
+
+  ScopedRunnableMethodFactory<ChannelImpl> factory_;
+
+  scoped_ptr<base::NonThreadSafe> thread_check_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_CHANNEL_WIN_H_
diff --git a/ipc/ipc_descriptors.h b/ipc/ipc_descriptors.h
new file mode 100644 (file)
index 0000000..4750fa8
--- /dev/null
@@ -0,0 +1,15 @@
+// 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 IPC_IPC_DESCRIPTORS_H_
+#define IPC_IPC_DESCRIPTORS_H_
+#pragma once
+
+// This is a list of global descriptor keys to be used with the
+// base::GlobalDescriptors object (see base/global_descriptors_posix.h)
+enum {
+  kPrimaryIPCChannel = 0,
+};
+
+#endif  // IPC_IPC_DESCRIPTORS_H_
diff --git a/ipc/ipc_export.h b/ipc/ipc_export.h
new file mode 100644 (file)
index 0000000..dc38fff
--- /dev/null
@@ -0,0 +1,29 @@
+// 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 IPC_IPC_OSP_EXPORT_
+#define IPC_IPC_OSP_EXPORT_
+#pragma once
+
+// Defines IPC_EXPORT so that functionality implemented by the IPC module can be
+// exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(IPC_IMPLEMENTATION)
+#define IPC_EXPORT __declspec(dllexport)
+#else
+#define IPC_EXPORT __declspec(dllimport)
+#endif  // defined(IPC_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#define IPC_EXPORT __attribute__((visibility("default")))
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define IPC_EXPORT
+#endif
+
+#endif  // IPC_IPC_OSP_EXPORT_
diff --git a/ipc/ipc_logging.cc b/ipc/ipc_logging.cc
new file mode 100644 (file)
index 0000000..138e6ac
--- /dev/null
@@ -0,0 +1,251 @@
+// 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 "ipc/ipc_logging.h"
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+#define IPC_MESSAGE_MACROS_LOG_ENABLED
+#endif
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/threading/thread.h"
+#include "base/time.h"
+#include "ipc/ipc_switches.h"
+#include "ipc/ipc_sync_message.h"
+#include "ipc/ipc_message_utils.h"
+
+#if defined(OS_POSIX)
+#include <unistd.h>
+#endif
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+
+using base::Time;
+
+// IPC::Logging is allocated as a singleton, so we don't need any kind of
+// special retention program.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(IPC::Logging);
+
+namespace IPC {
+
+const int kLogSendDelayMs = 100;
+
+// We use a pointer to the function table to avoid any linker dependencies on
+// all the traits used as IPC message parameters.
+LogFunctionMap* Logging::log_function_map_;
+
+Logging::Logging()
+    : enabled_(false),
+      enabled_on_stderr_(false),
+      queue_invoke_later_pending_(false),
+      sender_(NULL),
+      main_thread_(MessageLoop::current()),
+      consumer_(NULL) {
+#if defined(OS_WIN)
+  // getenv triggers an unsafe warning. Simply check how big of a buffer
+  // would be needed to fetch the value to see if the enviornment variable is
+  // set.
+  size_t requiredSize = 0;
+  getenv_s(&requiredSize, NULL, 0, "CHROME_IPC_LOGGING");
+  bool logging_env_var_set = (requiredSize != 0);
+#else  // !defined(OS_WIN)
+  bool logging_env_var_set = (getenv("CHROME_IPC_LOGGING") != NULL);
+#endif  //defined(OS_WIN)
+  if (logging_env_var_set) {
+    enabled_ = true;
+    enabled_on_stderr_ = true;
+  }
+}
+
+Logging::~Logging() {
+}
+
+Logging* Logging::GetInstance() {
+  return Singleton<Logging>::get();
+}
+
+void Logging::SetConsumer(Consumer* consumer) {
+  consumer_ = consumer;
+}
+
+void Logging::Enable() {
+  enabled_ = true;
+}
+
+void Logging::Disable() {
+  enabled_ = false;
+}
+
+void Logging::OnSendLogs() {
+  queue_invoke_later_pending_ = false;
+  if (!sender_)
+    return;
+
+  Message* msg = new Message(
+      MSG_ROUTING_CONTROL, IPC_LOGGING_ID, Message::PRIORITY_NORMAL);
+  WriteParam(msg, queued_logs_);
+  queued_logs_.clear();
+  sender_->Send(msg);
+}
+
+void Logging::SetIPCSender(IPC::Message::Sender* sender) {
+  sender_ = sender;
+}
+
+void Logging::OnReceivedLoggingMessage(const Message& message) {
+  std::vector<LogData> data;
+  void* iter = NULL;
+  if (!ReadParam(&message, &iter, &data))
+    return;
+
+  for (size_t i = 0; i < data.size(); ++i) {
+    Log(data[i]);
+  }
+}
+
+void Logging::OnSendMessage(Message* message, const std::string& channel_id) {
+  if (!Enabled())
+    return;
+
+  if (message->is_reply()) {
+    LogData* data = message->sync_log_data();
+    if (!data)
+      return;
+
+    // This is actually the delayed reply to a sync message.  Create a string
+    // of the output parameters, add it to the LogData that was earlier stashed
+    // with the reply, and log the result.
+    data->channel = channel_id;
+    GenerateLogData("", *message, data);
+    Log(*data);
+    delete data;
+    message->set_sync_log_data(NULL);
+  } else {
+    // If the time has already been set (i.e. by ChannelProxy), keep that time
+    // instead as it's more accurate.
+    if (!message->sent_time())
+      message->set_sent_time(Time::Now().ToInternalValue());
+  }
+}
+
+void Logging::OnPreDispatchMessage(const Message& message) {
+  message.set_received_time(Time::Now().ToInternalValue());
+}
+
+void Logging::OnPostDispatchMessage(const Message& message,
+                                    const std::string& channel_id) {
+  if (!Enabled() ||
+      !message.sent_time() ||
+      !message.received_time() ||
+      message.dont_log())
+    return;
+
+  LogData data;
+  GenerateLogData(channel_id, message, &data);
+
+  if (MessageLoop::current() == main_thread_) {
+    Log(data);
+  } else {
+    main_thread_->PostTask(FROM_HERE, NewRunnableMethod(
+        this, &Logging::Log, data));
+  }
+}
+
+void Logging::GetMessageText(uint32 type, std::string* name,
+                             const Message* message,
+                             std::string* params) {
+  if (!log_function_map_)
+    return;
+
+  LogFunctionMap::iterator it = log_function_map_->find(type);
+  if (it == log_function_map_->end()) {
+    if (name) {
+      *name = "[UNKNOWN MSG ";
+      *name += base::IntToString(type);
+      *name += " ]";
+    }
+    return;
+  }
+
+  (*it->second)(name, message, params);
+}
+
+void Logging::Log(const LogData& data) {
+  if (consumer_) {
+    // We're in the browser process.
+    consumer_->Log(data);
+  } else {
+    // We're in the renderer or plugin processes.
+    if (sender_) {
+      queued_logs_.push_back(data);
+      if (!queue_invoke_later_pending_) {
+        queue_invoke_later_pending_ = true;
+        MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(
+            this, &Logging::OnSendLogs), kLogSendDelayMs);
+      }
+    }
+  }
+  if (enabled_on_stderr_) {
+    std::string message_name;
+    if (data.message_name.empty()) {
+      message_name = StringPrintf("[unknown type %d]", data.type);
+    } else {
+      message_name = data.message_name;
+    }
+    fprintf(stderr, "ipc %s %d %s %s %s\n",
+            data.channel.c_str(),
+            data.routing_id,
+            data.flags.c_str(),
+            message_name.c_str(),
+            data.params.c_str());
+  }
+}
+
+void GenerateLogData(const std::string& channel, const Message& message,
+                     LogData* data) {
+  if (message.is_reply()) {
+    // "data" should already be filled in.
+    std::string params;
+    Logging::GetMessageText(data->type, NULL, &message, &params);
+
+    if (!data->params.empty() && !params.empty())
+      data->params += ", ";
+
+    data->flags += " DR";
+
+    data->params += params;
+  } else {
+    std::string flags;
+    if (message.is_sync())
+      flags = "S";
+
+    if (message.is_reply())
+      flags += "R";
+
+    if (message.is_reply_error())
+      flags += "E";
+
+    std::string params, message_name;
+    Logging::GetMessageText(message.type(), &message_name, &message, &params);
+
+    data->channel = channel;
+    data->routing_id = message.routing_id();
+    data->type = message.type();
+    data->flags = flags;
+    data->sent = message.sent_time();
+    data->receive = message.received_time();
+    data->dispatch = Time::Now().ToInternalValue();
+    data->params = params;
+    data->message_name = message_name;
+  }
+}
+
+}
+
+#endif  // IPC_MESSAGE_LOG_ENABLED
diff --git a/ipc/ipc_logging.h b/ipc/ipc_logging.h
new file mode 100644 (file)
index 0000000..42237c7
--- /dev/null
@@ -0,0 +1,112 @@
+// 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 IPC_IPC_LOGGING_H_
+#define IPC_IPC_LOGGING_H_
+#pragma once
+
+#include "ipc/ipc_message.h"  // For IPC_MESSAGE_LOG_ENABLED.
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+
+#include <vector>
+
+#include "base/hash_tables.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
+#include "base/message_loop.h"
+#include "ipc/ipc_export.h"
+
+// Logging function. |name| is a string in ASCII and |params| is a string in
+// UTF-8.
+typedef void (*LogFunction)(std::string* name,
+                            const IPC::Message* msg,
+                            std::string* params);
+
+typedef base::hash_map<uint32, LogFunction > LogFunctionMap;
+
+namespace IPC {
+
+class Message;
+
+// One instance per process.  Needs to be created on the main thread (the UI
+// thread in the browser) but OnPreDispatchMessage/OnPostDispatchMessage
+// can be called on other threads.
+class IPC_EXPORT Logging {
+ public:
+  // Implemented by consumers of log messages.
+  class Consumer {
+   public:
+    virtual void Log(const LogData& data) = 0;
+
+   protected:
+    virtual ~Consumer() {}
+  };
+
+  void SetConsumer(Consumer* consumer);
+
+  ~Logging();
+  static Logging* GetInstance();
+
+  // Enable and Disable are NOT cross-process; they only affect the
+  // current thread/process.  If you want to modify the value for all
+  // processes, perhaps your intent is to call
+  // g_browser_process->SetIPCLoggingEnabled().
+  void Enable();
+  void Disable();
+  bool Enabled() const { return enabled_; }
+
+  // Called by child processes to give the logger object the channel to send
+  // logging data to the browser process.
+  void SetIPCSender(Message::Sender* sender);
+
+  // Called in the browser process when logging data from a child process is
+  // received.
+  void OnReceivedLoggingMessage(const Message& message);
+
+  void OnSendMessage(Message* message, const std::string& channel_id);
+  void OnPreDispatchMessage(const Message& message);
+  void OnPostDispatchMessage(const Message& message,
+                             const std::string& channel_id);
+
+  // Like the *MsgLog functions declared for each message class, except this
+  // calls the correct one based on the message type automatically.  Defined in
+  // ipc_logging.cc.
+  static void GetMessageText(uint32 type, std::string* name,
+                             const Message* message, std::string* params);
+
+  static void set_log_function_map(LogFunctionMap* functions) {
+    log_function_map_ = functions;
+  }
+
+  static LogFunctionMap* log_function_map() {
+    return log_function_map_;
+  }
+
+ private:
+  friend struct DefaultSingletonTraits<Logging>;
+  Logging();
+
+  void OnSendLogs();
+  void Log(const LogData& data);
+
+  bool enabled_;
+  bool enabled_on_stderr_;  // only used on POSIX for now
+
+  std::vector<LogData> queued_logs_;
+  bool queue_invoke_later_pending_;
+
+  Message::Sender* sender_;
+  MessageLoop* main_thread_;
+
+  Consumer* consumer_;
+
+  static LogFunctionMap* log_function_map_;
+};
+
+}  // namespace IPC
+
+#endif // IPC_MESSAGE_LOG_ENABLED
+
+#endif  // IPC_IPC_LOGGING_H_
diff --git a/ipc/ipc_message.cc b/ipc/ipc_message.cc
new file mode 100644 (file)
index 0000000..235a7d5
--- /dev/null
@@ -0,0 +1,128 @@
+// 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 "ipc/ipc_message.h"
+
+//#include "base/logging.h"
+#include "log.h"
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+//#include "ipc/file_descriptor_set_posix.h"
+#endif
+
+namespace IPC {
+
+//------------------------------------------------------------------------------
+
+Message::~Message() {
+}
+
+Message::Message()
+    : Pickle(sizeof(Header)) {
+  header()->routing = header()->type = header()->flags = 0;
+#if defined(OS_POSIX)
+  header()->num_fds = 0;
+  header()->pad = 0;
+#endif
+  InitLoggingVariables();
+}
+
+Message::Message(int32 routing_id, uint32 type, PriorityValue priority)
+    : Pickle(sizeof(Header)) {
+  header()->routing = routing_id;
+  header()->type = type;
+  header()->flags = priority;
+#if defined(OS_POSIX)
+  header()->num_fds = 0;
+  header()->pad = 0;
+#endif
+  InitLoggingVariables();
+}
+
+Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
+  InitLoggingVariables();
+}
+
+Message::Message(const Message& other) : Pickle(other) {
+  InitLoggingVariables();
+#if defined(OS_POSIX)
+//  file_descriptor_set_ = other.file_descriptor_set_;
+#endif
+}
+
+void Message::InitLoggingVariables() {
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  received_time_ = 0;
+  dont_log_ = false;
+  log_data_ = NULL;
+#endif
+}
+
+Message& Message::operator=(const Message& other) {
+  *static_cast<Pickle*>(this) = other;
+#if defined(OS_POSIX)
+//  file_descriptor_set_ = other.file_descriptor_set_;
+#endif
+  return *this;
+}
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+void Message::set_sent_time(int64 time) {
+  DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
+  header()->flags |= HAS_SENT_TIME_BIT;
+  WriteInt64(time);
+}
+
+int64 Message::sent_time() const {
+  if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
+    return 0;
+
+  const char* data = end_of_payload();
+  data -= sizeof(int64);
+  return *(reinterpret_cast<const int64*>(data));
+}
+
+void Message::set_received_time(int64 time) const {
+  received_time_ = time;
+}
+#endif
+
+#if defined(OS_POSIX)
+/*
+bool Message::WriteFileDescriptor(const base::FileDescriptor& descriptor) {
+  // We write the index of the descriptor so that we don't have to
+  // keep the current descriptor as extra decoding state when deserialising.
+  WriteInt(file_descriptor_set()->size());
+  if (descriptor.auto_close) {
+    return file_descriptor_set()->AddAndAutoClose(descriptor.fd);
+  } else {
+    return file_descriptor_set()->Add(descriptor.fd);
+  }
+}
+
+bool Message::ReadFileDescriptor(void** iter,
+                                 base::FileDescriptor* descriptor) const {
+  int descriptor_index;
+  if (!ReadInt(iter, &descriptor_index))
+    return false;
+
+  FileDescriptorSet* file_descriptor_set = file_descriptor_set_.get();
+  if (!file_descriptor_set)
+    return false;
+
+  descriptor->fd = file_descriptor_set->GetDescriptorAt(descriptor_index);
+  descriptor->auto_close = true;
+
+  return descriptor->fd >= 0;
+}
+
+void Message::EnsureFileDescriptorSet() {
+  if (file_descriptor_set_.get() == NULL)
+    file_descriptor_set_ = new FileDescriptorSet;
+}
+*/
+#endif
+
+}  // namespace IPC
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h
new file mode 100644 (file)
index 0000000..11ed17c
--- /dev/null
@@ -0,0 +1,284 @@
+// 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 IPC_IPC_MESSAGE_H_
+#define IPC_IPC_MESSAGE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/pickle.h"
+#include "ipc/ipc_export.h"
+
+#ifndef NDEBUG
+//#define IPC_MESSAGE_LOG_ENABLED
+#endif
+
+#if defined(OS_POSIX)
+#include "base/memory/ref_counted.h"
+#endif
+
+namespace base {
+struct FileDescriptor;
+}
+
+class FileDescriptorSet;
+
+namespace IPC {
+
+//------------------------------------------------------------------------------
+
+class Channel;
+class Message;
+struct LogData;
+
+class IPC_EXPORT Message : public Pickle {
+ public:
+  // Implemented by objects that can send IPC messages across a channel.
+  class IPC_EXPORT Sender {
+   public:
+    virtual ~Sender() {}
+
+    // Sends the given IPC message.  The implementor takes ownership of the
+    // given Message regardless of whether or not this method succeeds.  This
+    // is done to make this method easier to use.  Returns true on success and
+    // false otherwise.
+    virtual bool Send(Message* msg) = 0;
+  };
+
+  enum PriorityValue {
+    PRIORITY_LOW = 1,
+    PRIORITY_NORMAL,
+    PRIORITY_HIGH
+  };
+
+  virtual ~Message();
+
+  Message();
+
+  // Initialize a message with a user-defined type, priority value, and
+  // destination WebView ID.
+  Message(int32 routing_id, uint32 type, PriorityValue priority);
+
+  // Initializes a message from a const block of data.  The data is not copied;
+  // instead the data is merely referenced by this message.  Only const methods
+  // should be used on the message when initialized this way.
+  Message(const char* data, int data_len);
+
+  Message(const Message& other);
+  Message& operator=(const Message& other);
+
+  PriorityValue priority() const {
+    return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
+  }
+
+  // True if this is a synchronous message.
+  bool is_sync() const {
+    return (header()->flags & SYNC_BIT) != 0;
+  }
+
+  // Set this on a reply to a synchronous message.
+  void set_reply() {
+    header()->flags |= REPLY_BIT;
+  }
+
+  bool is_reply() const {
+    return (header()->flags & REPLY_BIT) != 0;
+  }
+
+  // Set this on a reply to a synchronous message to indicate that no receiver
+  // was found.
+  void set_reply_error() {
+    header()->flags |= REPLY_ERROR_BIT;
+  }
+
+  bool is_reply_error() const {
+    return (header()->flags & REPLY_ERROR_BIT) != 0;
+  }
+
+  // Normally when a receiver gets a message and they're blocked on a
+  // synchronous message Send, they buffer a message.  Setting this flag causes
+  // the receiver to be unblocked and the message to be dispatched immediately.
+  void set_unblock(bool unblock) {
+    if (unblock) {
+      header()->flags |= UNBLOCK_BIT;
+    } else {
+      header()->flags &= ~UNBLOCK_BIT;
+    }
+  }
+
+  bool should_unblock() const {
+    return (header()->flags & UNBLOCK_BIT) != 0;
+  }
+
+  // Tells the receiver that the caller is pumping messages while waiting
+  // for the result.
+  bool is_caller_pumping_messages() const {
+    return (header()->flags & PUMPING_MSGS_BIT) != 0;
+  }
+
+  uint32 type() const {
+    return header()->type;
+  }
+
+  int32 routing_id() const {
+    return header()->routing;
+  }
+
+  void set_routing_id(int32 new_id) {
+    header()->routing = new_id;
+  }
+
+  template<class T, class S>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)()) {
+    (obj->*func)();
+    return true;
+  }
+
+  template<class T, class S>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)() const) {
+    (obj->*func)();
+    return true;
+  }
+
+  template<class T, class S>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)(const Message&)) {
+    (obj->*func)(*msg);
+    return true;
+  }
+
+  template<class T, class S>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)(const Message&) const) {
+    (obj->*func)(*msg);
+    return true;
+  }
+
+  // Used for async messages with no parameters.
+  static void Log(std::string* name, const Message* msg, std::string* l) {
+  }
+
+  // Find the end of the message data that starts at range_start.  Returns NULL
+  // if the entire message is not found in the given data range.
+  static const char* FindNext(const char* range_start, const char* range_end) {
+    return Pickle::FindNext(sizeof(Header), range_start, range_end);
+  }
+
+#if defined(OS_POSIX)
+  // On POSIX, a message supports reading / writing FileDescriptor objects.
+  // This is used to pass a file descriptor to the peer of an IPC channel.
+
+  // Add a descriptor to the end of the set. Returns false iff the set is full.
+//  bool WriteFileDescriptor(const base::FileDescriptor& descriptor);
+  // Get a file descriptor from the message. Returns false on error.
+  //   iter: a Pickle iterator to the current location in the message.
+//  bool ReadFileDescriptor(void** iter, base::FileDescriptor* descriptor) const;
+#endif
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  // Adds the outgoing time from Time::Now() at the end of the message and sets
+  // a bit to indicate that it's been added.
+  void set_sent_time(int64 time);
+  int64 sent_time() const;
+
+  void set_received_time(int64 time) const;
+  int64 received_time() const { return received_time_; }
+  void set_output_params(const std::string& op) const { output_params_ = op; }
+  const std::string& output_params() const { return output_params_; }
+  // The following four functions are needed so we can log sync messages with
+  // delayed replies.  We stick the log data from the sent message into the
+  // reply message, so that when it's sent and we have the output parameters
+  // we can log it.  As such, we set a flag on the sent message to not log it.
+  void set_sync_log_data(LogData* data) const { log_data_ = data; }
+  LogData* sync_log_data() const { return log_data_; }
+  void set_dont_log() const { dont_log_ = true; }
+  bool dont_log() const { return dont_log_; }
+#endif
+
+ protected:
+  friend class Channel;
+  friend class MessageReplyDeserializer;
+  friend class SyncMessage;
+
+  void set_sync() {
+    header()->flags |= SYNC_BIT;
+  }
+
+  // flags
+  enum {
+    PRIORITY_MASK   = 0x0003,
+    SYNC_BIT        = 0x0004,
+    REPLY_BIT       = 0x0008,
+    REPLY_ERROR_BIT = 0x0010,
+    UNBLOCK_BIT     = 0x0020,
+    PUMPING_MSGS_BIT= 0x0040,
+    HAS_SENT_TIME_BIT = 0x0080,
+  };
+
+#pragma pack(push, 4)
+  struct Header : Pickle::Header {
+    int32 routing;  // ID of the view that this message is destined for
+    uint32 type;    // specifies the user-defined message type
+    uint32 flags;   // specifies control flags for the message
+#if defined(OS_POSIX)
+    uint16 num_fds; // the number of descriptors included with this message
+    uint16 pad;     // explicitly initialize this to appease valgrind
+#endif
+  };
+#pragma pack(pop)
+
+  Header* header() {
+    return headerT<Header>();
+  }
+  const Header* header() const {
+    return headerT<Header>();
+  }
+
+  void InitLoggingVariables();
+
+#if defined(OS_POSIX)
+  // The set of file descriptors associated with this message.
+//  scoped_refptr<FileDescriptorSet> file_descriptor_set_;
+
+  // Ensure that a FileDescriptorSet is allocated
+//  void EnsureFileDescriptorSet();
+
+//  FileDescriptorSet* file_descriptor_set() {
+//    EnsureFileDescriptorSet();
+//    return file_descriptor_set_.get();
+//  }
+//  const FileDescriptorSet* file_descriptor_set() const {
+//    return file_descriptor_set_.get();
+//  }
+#endif
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  // Used for logging.
+  mutable int64 received_time_;
+  mutable std::string output_params_;
+  mutable LogData* log_data_;
+  mutable bool dont_log_;
+#endif
+};
+
+//------------------------------------------------------------------------------
+
+}  // namespace IPC
+
+enum SpecialRoutingIDs {
+  // indicates that we don't have a routing ID yet.
+  MSG_ROUTING_NONE = -2,
+
+  // indicates a general message not sent to a particular tab.
+  MSG_ROUTING_CONTROL = kint32max,
+};
+
+#define IPC_REPLY_ID 0xFFFFFFF0  // Special message id for replies
+#define IPC_LOGGING_ID 0xFFFFFFF1  // Special message id for logging
+
+#endif  // IPC_IPC_MESSAGE_H_
diff --git a/ipc/ipc_message_macros.h b/ipc/ipc_message_macros.h
new file mode 100644 (file)
index 0000000..302d125
--- /dev/null
@@ -0,0 +1,822 @@
+// 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.
+
+// Defining IPC Messages
+//
+// Your IPC messages will be defined by macros inside of an XXX_messages.h
+// header file.  Most of the time, the system can automatically generate all
+// of messaging mechanism from these definitions, but sometimes some manual
+// coding is required.  In these cases, you will also have an XXX_messages.cc
+// implemation file as well.
+//
+// The senders of your messages will include your XXX_messages.h file to
+// get the full set of definitions they need to send your messages.
+//
+// Each XXX_messages.h file must be registered with the IPC system.  This
+// requires adding two things:
+//   - An XXXMsgStart value to the IPCMessageStart enum in ipc_message_utils.h
+//   - An inclusion of XXX_messages.h file in a message generator .h file
+//
+// The XXXMsgStart value is an enumeration that ensures uniqueness for
+// each different message file.  Later, you will use this inside your
+// XXX_messages.h file before invoking message declatation macros:
+//     #define IPC_MESSAGE_START XXXMsgStart
+//       ( ... your macro invocations go here ... )
+//
+// Message Generator Files
+//
+// A message generator .h header file pulls in all other message-declaring
+// headers for a given component.  It is included by a message generator
+// .cc file, which is where all the generated code will wind up.  Typically,
+// you will use an existing generator (e.g. common_message_generator.cc
+// in /chrome/common), but there are circumstances where you may add a
+// new one.
+//
+// In the rare cicrucmstances where you can't re-use an existing file,
+// your YYY_message_generator.cc file for a component YYY would contain
+// the following code:
+//     // Get basic type definitions.
+//     #define IPC_MESSAGE_IMPL
+//     #include "path/to/YYY_message_generator.h"
+//     // Generate constructors.
+//     #include "ipc/struct_constructor_macros.h"
+//     #include "path/to/YYY_message_generator.h"
+//     // Generate destructors.
+//     #include "ipc/struct_destructor_macros.h"
+//     #include "path/to/YYY_message_generator.h"
+//     // Generate param traits write methods.
+//     #include "ipc/param_traits_write_macros.h"
+//     namespace IPC {
+//     #include "path/to/YYY_message_generator.h"
+//     }  // namespace IPC
+//     // Generate param traits read methods.
+//     #include "ipc/param_traits_read_macros.h"
+//     namespace IPC {
+//     #include "path/to/YYY_message_generator.h"
+//     }  // namespace IPC
+//     // Generate param traits log methods.
+//     #include "ipc/param_traits_log_macros.h"
+//     namespace IPC {
+//     #include "path/to/YYY_message_generator.h"
+//     }  // namespace IPC
+//
+// In cases where manual generation is required, in your XXX_messages.cc
+// file, put the following after all the includes for param types:
+//     #define IPC_MESSAGE_IMPL
+//     #include "XXX_messages.h"
+//        (... implementation of traits not auto-generated ...)
+//
+// Multiple Inclusion
+//
+// The XXX_messages.h file will be multiply-included by the
+// YYY_message_generator.cc file, so your XXX_messages file can't be
+// guarded in the usual manner.  Ideally, there will be no need for any
+// inclusion guard, since the XXX_messages.h file should consist soley
+// of inclusions of other headers (which are self-guarding) and IPC
+// macros (which are multiply evaluating).
+//
+// Note that there is no #pragma once either; doing so would mark the whole
+// file as being singly-included.  Since your XXX_messages.h file is only
+// partially-guarded, care must be taken to ensure that it is only included
+// by other .cc files (and the YYY_message_generator.h file).  Including an
+// XXX_messages.h file in some other .h file may result in duplicate
+// declarations and a compilation failure.
+//
+// Type Declarations
+//
+// It is generally a bad idea to have type definitions in a XXX_messages.h
+// file; most likely the typedef will then be used in the message, as opposed
+// to the struct iself.  Later, an IPC message dispatcher wil need to call
+// a function taking that type, and that function is declared in some other
+// header.  Thus, in order to get the type definition, the other header
+// would have to include the XXX_messages.h file, violating the rule above
+// about not including XXX_messages.h file in other .h files.
+//
+// One approach here is to move these type definitions to another (guarded)
+// .h file and include this second .h in your XXX_messages.h file.  This
+// is still less than ideal, because the dispatched function would have to
+// redeclare the typedef or include this second header.  This may be
+// reasonable in a few cases.
+//
+// Failing all of the above, then you will want to bracket the smallest
+// possible section of your XXX_messages.h file containing these types
+// with an include guard macro.  Be aware that providing an incomplete
+// class type declaration to avoid pulling in a long chain of headers is
+// acceptable when your XXX_messages.h header is being included by the
+// message sending caller's code, but not when the YYY_message_generator.c
+// is building the messages. In addtion, due to the multiple inclusion
+// restriction, these type ought to be guarded.  Follow a convention like:
+//      #ifndef SOME_GUARD_MACRO
+//      #define SOME_GUARD_MACRO
+//      class some_class;        // One incomplete class declaration
+//      class_some_other_class;  // Another incomplete class declaration
+//      #endif  // SOME_GUARD_MACRO
+//      #ifdef IPC_MESSAGE_IMPL
+//      #inlcude "path/to/some_class.h"        // Full class declaration
+//      #inlcude "path/to/some_other_class.h"  // Full class declaration
+//      #endif  // IPC_MESSAGE_IMPL
+//        (.. IPC macros using some_class and some_other_class ...)
+//
+// Macro Invocations
+//
+// You will use IPC message macro invocations for three things:
+//   - New struct definitions for IPC
+//   - Registering existing struct and enum definitions with IPC
+//   - Defining the messages themselves
+//
+// New structs are defined with IPC_STRUCT_BEGIN(), IPC_STRUCT_MEMBER(),
+// IPC_STRUCT_END() family of macros.  These cause the XXX_messages.h
+// to proclaim equivalent struct declarations for use by callers, as well
+// as later registering the type with the message generation.  Note that
+// IPC_STRUCT_MEMBER() is only permitted inside matching calls to
+// IPC_STRUCT_BEGIN() / IPC_STRUCT_END().
+//
+// Externally-defined structs are registered with IPC_STRUCT_TRAITS_BEGIN(),
+// IPC_STRUCT_TRAITS_MEMBER(), and IPC_STRUCT_TRAITS_END() macros. These
+// cause registration of the types with message generation only.
+// There's also IPC_STRUCT_TRAITS_PARENT, which is used to register a parent
+// class (whose own traits are already defined). Note that
+// IPC_STRUCT_TRAITS_MEMBER() and IPC_STRUCT_TRAITS_PARENT are only permitted
+// inside matching calls to IPC_STRUCT_TRAITS_BEGIN() /
+// IPC_STRUCT_TRAITS_END().
+//
+// Enum types are registered with a single IPC_ENUM_TRAITS() macro.  There
+// is no need to enumerate each value to the IPC mechanism.
+//
+// Do not place semicolons following these IPC_ macro invocations.  There
+// is no reason to expect that their expansion corresponds one-to-one with
+// C++ statements.
+//
+// Once the types have been declared / registered, message definitions follow.
+// "Sync" messages are just synchronous calls, the Send() call doesn't return
+// until a reply comes back.  Input parameters are first (const TYPE&), and
+// To declare a sync message, use the IPC_SYNC_ macros.  The numbers at the
+// end show how many input/output parameters there are (i.e. 1_2 is 1 in, 2
+// out). The caller does a Send([route id, ], in1, &out1, &out2).
+// The receiver's handler function will be
+//     void OnSyncMessageName(const type1& in1, type2* out1, type3* out2)
+//
+// A caller can also send a synchronous message, while the receiver can respond
+// at a later time.  This is transparent from the sender's side.  The receiver
+// needs to use a different handler that takes in a IPC::Message* as the output
+// type, stash the message, and when it has the data it can Send the message.
+//
+// Use the IPC_MESSAGE_HANDLER_DELAY_REPLY macro instead of IPC_MESSAGE_HANDLER
+//     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SyncMessageName,
+//                                     OnSyncMessageName)
+//
+// The handler function will look like:
+//     void OnSyncMessageName(const type1& in1, IPC::Message* reply_msg);
+//
+// Receiver stashes the IPC::Message* pointer, and when it's ready, it does:
+//     ViewHostMsg_SyncMessageName::WriteReplyParams(reply_msg, out1, out2);
+//     Send(reply_msg);
+
+#ifndef IPC_IPC_MESSAGE_MACROS_H_
+#define IPC_IPC_MESSAGE_MACROS_H_
+
+#include "ipc/ipc_message_utils.h"
+#include "ipc/param_traits_macros.h"
+
+#if defined(IPC_MESSAGE_IMPL)
+#include "ipc/ipc_message_utils_impl.h"
+#endif
+
+// Macros for defining structs.  May be subsequently redefined.
+#define IPC_STRUCT_BEGIN(struct_name) \
+  struct struct_name; \
+  IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+  IPC_STRUCT_TRAITS_END() \
+  struct struct_name : IPC::NoParams { \
+    struct_name(); \
+    ~struct_name();
+#define IPC_STRUCT_MEMBER(type, name) type name;
+#define IPC_STRUCT_END() };
+
+// Message macros collect specific numbers of arguments and funnel them into
+// the common message generation macro.  These should never be redefined.
+#define IPC_MESSAGE_CONTROL0(msg_class) \
+  IPC_MESSAGE_DECL(EMPTY, CONTROL, msg_class, 0, 0, (), ())
+
+#define IPC_MESSAGE_CONTROL1(msg_class, type1) \
+  IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 1, 0, (type1), ())
+
+#define IPC_MESSAGE_CONTROL2(msg_class, type1, type2) \
+  IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 2, 0, (type1, type2), ())
+
+#define IPC_MESSAGE_CONTROL3(msg_class, type1, type2, type3) \
+  IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 3, 0, (type1, type2, type3), ())
+
+#define IPC_MESSAGE_CONTROL4(msg_class, type1, type2, type3, type4) \
+  IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 4, 0, (type1, type2, type3, type4), ())
+
+#define IPC_MESSAGE_CONTROL5(msg_class, type1, type2, type3, type4, type5) \
+  IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 5, 0, (type1, type2, type3, type4, type5), ())
+
+#define IPC_MESSAGE_CONTROL6(msg_class, type1, type2, type3, type4, type5, type6) \
+       IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 6, 0, (type1, type2, type3, type4, type5, type6), ())
+
+
+#define IPC_MESSAGE_ROUTED0(msg_class) \
+  IPC_MESSAGE_DECL(EMPTY, ROUTED, msg_class, 0, 0, (), ())
+
+#define IPC_MESSAGE_ROUTED1(msg_class, type1) \
+  IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 1, 0, (type1), ())
+
+#define IPC_MESSAGE_ROUTED2(msg_class, type1, type2) \
+  IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 2, 0, (type1, type2), ())
+
+#define IPC_MESSAGE_ROUTED3(msg_class, type1, type2, type3) \
+  IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 3, 0, (type1, type2, type3), ())
+
+#define IPC_MESSAGE_ROUTED4(msg_class, type1, type2, type3, type4) \
+  IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 4, 0, (type1, type2, type3, type4), ())
+
+#define IPC_MESSAGE_ROUTED5(msg_class, type1, type2, type3, type4, type5) \
+  IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 5, 0, (type1, type2, type3, type4, type5), ())
+
+#define IPC_MESSAGE_ROUTED6(msg_class, type1, type2, type3, type4, type5, type6) \
+       IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 6, 0, (type1, type2, type3, type4, type5, type6), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL0_0(msg_class) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 0, (), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL0_1(msg_class, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 1, (), (type1_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL0_2(msg_class, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 2, (), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL0_3(msg_class, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 3, (), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL0_4(msg_class, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 4, (), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL1_0(msg_class, type1_in) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 0, (type1_in), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL1_1(msg_class, type1_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 1, (type1_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL1_2(msg_class, type1_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 2, (type1_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL1_3(msg_class, type1_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 3, (type1_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL1_4(msg_class, type1_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 4, (type1_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL2_0(msg_class, type1_in, type2_in) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 0, (type1_in, type2_in), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL2_1(msg_class, type1_in, type2_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 1, (type1_in, type2_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL2_2(msg_class, type1_in, type2_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 2, (type1_in, type2_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL2_3(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 3, (type1_in, type2_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL2_4(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 4, (type1_in, type2_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL3_0(msg_class, type1_in, type2_in, type3_in) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 0, (type1_in, type2_in, type3_in), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL3_1(msg_class, type1_in, type2_in, type3_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 1, (type1_in, type2_in, type3_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL3_2(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 2, (type1_in, type2_in, type3_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL3_3(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 3, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL3_4(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 4, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL4_0(msg_class, type1_in, type2_in, type3_in, type4_in) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 0, (type1_in, type2_in, type3_in, type4_in), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL4_1(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 1, (type1_in, type2_in, type3_in, type4_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL4_2(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 2, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL4_3(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 3, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL4_4(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 4, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL5_0(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 0, (type1_in, type2_in, type3_in, type4_in, type5_in), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL5_1(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 1, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL5_2(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 2, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL5_3(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 3, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL5_4(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 4, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_CONTROL6_0(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type6_in) \
+       IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 6, 0, (type1_in, type2_in, type3_in, type4_in, type5_in, type6_in), ())
+
+#define IPC_SYNC_MESSAGE_CONTROL6_1(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type6_in, type1_out) \
+       IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 6, 1, (type1_in, type2_in, type3_in, type4_in, type5_in, type6_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED0_0(msg_class) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 0, (), ())
+
+#define IPC_SYNC_MESSAGE_ROUTED0_1(msg_class, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 1, (), (type1_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED0_2(msg_class, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 2, (), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED0_3(msg_class, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 3, (), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED0_4(msg_class, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 4, (), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED1_0(msg_class, type1_in) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 0, (type1_in), ())
+
+#define IPC_SYNC_MESSAGE_ROUTED1_1(msg_class, type1_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 1, (type1_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED1_2(msg_class, type1_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 2, (type1_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED1_3(msg_class, type1_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 3, (type1_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED1_4(msg_class, type1_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 4, (type1_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED2_0(msg_class, type1_in, type2_in) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 0, (type1_in, type2_in), ())
+
+#define IPC_SYNC_MESSAGE_ROUTED2_1(msg_class, type1_in, type2_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 1, (type1_in, type2_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED2_2(msg_class, type1_in, type2_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 2, (type1_in, type2_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED2_3(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 3, (type1_in, type2_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED2_4(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 4, (type1_in, type2_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED3_0(msg_class, type1_in, type2_in, type3_in) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 0, (type1_in, type2_in, type3_in), ())
+
+#define IPC_SYNC_MESSAGE_ROUTED3_1(msg_class, type1_in, type2_in, type3_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 1, (type1_in, type2_in, type3_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED3_2(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 2, (type1_in, type2_in, type3_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED3_3(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 3, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED3_4(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 4, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED4_0(msg_class, type1_in, type2_in, type3_in, type4_in) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 1, (type1_in, type2_in, type3_in, type4_in), ())
+
+#define IPC_SYNC_MESSAGE_ROUTED4_1(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 1, (type1_in, type2_in, type3_in, type4_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED4_2(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 2, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED4_3(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 3, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED4_4(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 4, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out, type4_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED5_0(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 1, (type1_in, type2_in, type3_in, type4_in, type5_in), ())
+
+#define IPC_SYNC_MESSAGE_ROUTED5_1(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 1, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED5_2(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 2, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED5_3(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 3, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out, type3_out))
+
+#define IPC_SYNC_MESSAGE_ROUTED5_4(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out, type4_out) \
+  IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 4, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out, type3_out, type4_out))
+
+// Common message macro which dispatches into one of the 6 (sync x kind)
+// routines.  There is a way that these 6 cases can be lumped together,
+// but the  macros get very complicated in that case.
+// Note: intended be redefined to generate other information.
+#define IPC_MESSAGE_DECL(sync, kind, msg_class,                               \
+                         in_cnt, out_cnt, in_list, out_list)                  \
+  IPC_##sync##_##kind##_DECL(msg_class, in_cnt, out_cnt, in_list, out_list)   \
+  IPC_MESSAGE_EXTRA(sync, kind, msg_class, in_cnt, out_cnt, in_list, out_list)
+
+#define IPC_EMPTY_CONTROL_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
+  class __attribute__((visibility("default"))) msg_class : public IPC::Message\
+  {                                                                           \
+   public:                                                                    \
+    enum { ID = IPC_MESSAGE_ID() };                                           \
+    msg_class() : IPC::Message(MSG_ROUTING_CONTROL, ID, PRIORITY_NORMAL) {}   \
+  };
+
+#define IPC_EMPTY_ROUTED_DECL(msg_class, in_cnt, out_cnt, in_list, out_list)  \
+  class __attribute__((visibility("default"))) msg_class : public IPC::Message\
+  {                                                                           \
+   public:                                                                    \
+    enum { ID = IPC_MESSAGE_ID() };                                           \
+    msg_class(int32 routing_id)                                               \
+        : IPC::Message(routing_id, ID, PRIORITY_NORMAL) {}                    \
+  };
+
+#define IPC_ASYNC_CONTROL_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
+  class __attribute__((visibility("default"))) msg_class :                    \
+      public IPC::MessageWithTuple<IPC_TUPLE_IN_##in_cnt in_list> {           \
+   public:                                                                    \
+    enum { ID = IPC_MESSAGE_ID() };                                           \
+    msg_class(IPC_TYPE_IN_##in_cnt in_list);                                  \
+    virtual ~msg_class();                                                     \
+    static void Log(std::string* name, const Message* msg, std::string* l);   \
+  };
+
+#define IPC_ASYNC_ROUTED_DECL(msg_class, in_cnt, out_cnt, in_list, out_list)  \
+  class __attribute__((visibility("default"))) msg_class :                    \
+      public IPC::MessageWithTuple<IPC_TUPLE_IN_##in_cnt in_list> {           \
+   public:                                                                    \
+    enum { ID = IPC_MESSAGE_ID() };                                           \
+    msg_class(int32 routing_id IPC_COMMA_##in_cnt                             \
+              IPC_TYPE_IN_##in_cnt in_list);                                  \
+    virtual ~msg_class();                                                     \
+    static void Log(std::string* name, const Message* msg, std::string* l);   \
+  };
+
+#define IPC_SYNC_CONTROL_DECL(msg_class, in_cnt, out_cnt, in_list, out_list)  \
+  class __attribute__((visibility("default"))) msg_class :                    \
+      public IPC::MessageWithReply<IPC_TUPLE_IN_##in_cnt in_list,             \
+                                   IPC_TUPLE_OUT_##out_cnt out_list> {        \
+   public:                                                                    \
+    enum { ID = IPC_MESSAGE_ID() };                                           \
+    msg_class(IPC_TYPE_IN_##in_cnt in_list                                    \
+              IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt)                     \
+              IPC_TYPE_OUT_##out_cnt out_list);                               \
+    virtual ~msg_class();                                                     \
+    static void Log(std::string* name, const Message* msg, std::string* l);   \
+  };
+
+#define IPC_SYNC_ROUTED_DECL(msg_class, in_cnt, out_cnt, in_list, out_list)   \
+  class __attribute__((visibility("default"))) msg_class :                    \
+      public IPC::MessageWithReply<IPC_TUPLE_IN_##in_cnt in_list,             \
+                                   IPC_TUPLE_OUT_##out_cnt out_list> {        \
+   public:                                                                    \
+    enum { ID = IPC_MESSAGE_ID() };                                           \
+    msg_class(int32 routing_id                                                \
+              IPC_COMMA_OR_##in_cnt(IPC_COMMA_##out_cnt)                      \
+              IPC_TYPE_IN_##in_cnt in_list                                    \
+              IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt)                     \
+              IPC_TYPE_OUT_##out_cnt out_list);                               \
+    virtual ~msg_class();                                                     \
+    static void Log(std::string* name, const Message* msg, std::string* l);   \
+  };
+
+#if defined(IPC_MESSAGE_IMPL)
+
+// "Implementation" inclusion produces constructors, destructors, and
+// logging functions, except for the no-arg special cases, where the
+// implementation occurs in the declaration, and there is no special
+// logging function.
+#define IPC_MESSAGE_EXTRA(sync, kind, msg_class,                              \
+                          in_cnt, out_cnt, in_list, out_list)                 \
+  IPC_##sync##_##kind##_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)   \
+  IPC_##sync##_MESSAGE_LOG(msg_class)
+
+#define IPC_EMPTY_CONTROL_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)
+#define IPC_EMPTY_ROUTED_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)
+
+#define IPC_ASYNC_CONTROL_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list) \
+  msg_class::msg_class(IPC_TYPE_IN_##in_cnt in_list) :                        \
+      IPC::MessageWithTuple<IPC_TUPLE_IN_##in_cnt in_list>                    \
+      (MSG_ROUTING_CONTROL, ID, IPC_NAME_IN_##in_cnt in_list)                 \
+      {}                                                                      \
+  msg_class::~msg_class() {}
+
+#define IPC_ASYNC_ROUTED_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)  \
+  msg_class::msg_class(int32 routing_id IPC_COMMA_##in_cnt                    \
+                       IPC_TYPE_IN_##in_cnt in_list) :                        \
+      IPC::MessageWithTuple<IPC_TUPLE_IN_##in_cnt in_list>                    \
+      (routing_id, ID, IPC_NAME_IN_##in_cnt in_list)                          \
+      {}                                                                      \
+  msg_class::~msg_class() {}
+
+#define IPC_SYNC_CONTROL_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)  \
+  msg_class::msg_class(IPC_TYPE_IN_##in_cnt in_list                           \
+                       IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt)            \
+                       IPC_TYPE_OUT_##out_cnt out_list) :                     \
+      IPC::MessageWithReply<IPC_TUPLE_IN_##in_cnt in_list,                    \
+                            IPC_TUPLE_OUT_##out_cnt out_list>                 \
+      (MSG_ROUTING_CONTROL, ID,                                               \
+       IPC_NAME_IN_##in_cnt in_list,                                          \
+       IPC_NAME_OUT_##out_cnt out_list)                                       \
+  {                                                                    \
+  }                                                                    \
+  msg_class::~msg_class() {}
+
+#define IPC_SYNC_ROUTED_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)   \
+  msg_class::msg_class(int32 routing_id                                       \
+                       IPC_COMMA_OR_##in_cnt(IPC_COMMA_##out_cnt)             \
+                       IPC_TYPE_IN_##in_cnt in_list                           \
+                       IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt)            \
+                       IPC_TYPE_OUT_##out_cnt out_list) :                     \
+      IPC::MessageWithReply<IPC_TUPLE_IN_##in_cnt in_list,                    \
+                            IPC_TUPLE_OUT_##out_cnt out_list>                 \
+      (routing_id, ID,                                                        \
+       IPC_NAME_IN_##in_cnt in_list,                                          \
+       IPC_NAME_OUT_##out_cnt out_list)                                       \
+      {}                                                                      \
+  msg_class::~msg_class() {}
+
+#define IPC_EMPTY_MESSAGE_LOG(msg_class)
+
+#define IPC_ASYNC_MESSAGE_LOG(msg_class)                                \
+  void msg_class::Log(std::string* name,                                \
+                      const Message* msg,                               \
+                      std::string* l) {                                 \
+    if (name)                                                           \
+       {                                                                                                                                       \
+      *name = #msg_class;                                               \
+       }                                                                                                                                       \
+    if (!msg || !l)                                                     \
+       {                                                                                                                                       \
+      return;                                                           \
+       }                                                                                                                                       \
+    Param p;                                                            \
+    if (Read(msg, &p))                                                  \
+       {                                                                                                                                       \
+      IPC::LogParam(p, l);                                              \
+       }                                                                                                                                       \
+  }
+
+#define IPC_SYNC_MESSAGE_LOG(msg_class)                                 \
+  void msg_class::Log(std::string* name,                                \
+                      const Message* msg,                               \
+                      std::string* l) {                                 \
+    if (name)                                                           \
+       {                                                                                                                                       \
+      *name = #msg_class;                                               \
+       }                                                                                                                                       \
+    if (!msg || !l)                                                     \
+       {                                                                                                                                       \
+      return;                                                           \
+       }                                                                                                                                       \
+    if (msg->is_sync()) {                                               \
+      TupleTypes<SendParam>::ValueTuple p;                              \
+      if (ReadSendParam(msg, &p))                                       \
+         {                                                                                                                                     \
+        IPC::LogParam(p, l);                                            \
+         }                                                                                                                                     \
+      AddOutputParamsToLog(msg, l);                                     \
+    } else {                                                            \
+      TupleTypes<ReplyParam>::ValueTuple p;                             \
+      if (ReadReplyParam(msg, &p))                                      \
+         {                                                                                                                                     \
+        IPC::LogParam(p, l);                                            \
+         }                                                                                                                                     \
+    }                                                                   \
+  }
+
+#elif defined(IPC_MESSAGE_MACROS_LOG_ENABLED)
+
+#ifndef IPC_LOG_TABLE_CREATED
+#define IPC_LOG_TABLE_CREATED
+
+#include "base/hash_tables.h"
+
+typedef void (*LogFunction)(std::string* name,
+                            const IPC::Message* msg,
+                            std::string* params);
+
+typedef base::hash_map<uint32, LogFunction > LogFunctionMap;
+LogFunctionMap g_log_function_mapping;
+
+#endif  // IPC_LOG_TABLE_CREATED
+
+// "Log table" inclusion produces extra logging registration code.
+#define IPC_MESSAGE_EXTRA(sync, kind, msg_class,                        \
+                          in_cnt, out_cnt, in_list, out_list)           \
+  class __attribute__((visibility("default"))) LoggerRegisterHelper##msg_class { \
+ public:                                                                \
+    LoggerRegisterHelper##msg_class() {                                 \
+      g_log_function_mapping[msg_class::ID] = msg_class::Log;           \
+    }                                                                   \
+  };                                                                    \
+  LoggerRegisterHelper##msg_class g_LoggerRegisterHelper##msg_class;
+
+#else
+
+// Normal inclusion produces nothing extra.
+#define IPC_MESSAGE_EXTRA(sync, kind, msg_class,                \
+                          in_cnt, out_cnt, in_list, out_list)
+
+#endif // defined(IPC_MESSAGE_IMPL)
+
+// Handle variable sized argument lists.  These are usually invoked by token
+// pasting against the argument counts.
+#define IPC_TYPE_IN_0()
+#define IPC_TYPE_IN_1(t1)                   const t1& arg1
+#define IPC_TYPE_IN_2(t1, t2)               const t1& arg1, const t2& arg2
+#define IPC_TYPE_IN_3(t1, t2, t3)           const t1& arg1, const t2& arg2, const t3& arg3
+#define IPC_TYPE_IN_4(t1, t2, t3, t4)       const t1& arg1, const t2& arg2, const t3& arg3, const t4& arg4
+#define IPC_TYPE_IN_5(t1, t2, t3, t4, t5)   const t1& arg1, const t2& arg2, const t3& arg3, const t4& arg4, const t5& arg5
+#define IPC_TYPE_IN_6(t1, t2, t3, t4, t5, t6)   const t1& arg1, const t2& arg2, const t3& arg3, const t4& arg4, const t5& arg5, const t6& arg6
+
+#define IPC_TYPE_OUT_0()
+#define IPC_TYPE_OUT_1(t1)                  t1* arg7
+#define IPC_TYPE_OUT_2(t1, t2)              t1* arg7, t2* arg8
+#define IPC_TYPE_OUT_3(t1, t2, t3)          t1* arg7, t2* arg8, t3* arg9
+#define IPC_TYPE_OUT_4(t1, t2, t3, t4)      t1* arg7, t2* arg8, t3* arg9, t4* arg10
+
+#define IPC_TUPLE_IN_0()                    Tuple0
+#define IPC_TUPLE_IN_1(t1)                  Tuple1<t1>
+#define IPC_TUPLE_IN_2(t1, t2)              Tuple2<t1, t2>
+#define IPC_TUPLE_IN_3(t1, t2, t3)          Tuple3<t1, t2, t3>
+#define IPC_TUPLE_IN_4(t1, t2, t3, t4)      Tuple4<t1, t2, t3, t4>
+#define IPC_TUPLE_IN_5(t1, t2, t3, t4, t5)  Tuple5<t1, t2, t3, t4, t5>
+#define IPC_TUPLE_IN_6(t1, t2, t3, t4, t5, t6)  Tuple6<t1, t2, t3, t4, t5, t6>
+
+#define IPC_TUPLE_OUT_0()                   Tuple0
+#define IPC_TUPLE_OUT_1(t1)                 Tuple1<t1&>
+#define IPC_TUPLE_OUT_2(t1, t2)             Tuple2<t1&, t2&>
+#define IPC_TUPLE_OUT_3(t1, t2, t3)         Tuple3<t1&, t2&, t3&>
+#define IPC_TUPLE_OUT_4(t1, t2, t3, t4)     Tuple4<t1&, t2&, t3&, t4&>
+
+#define IPC_NAME_IN_0()                     MakeTuple()
+#define IPC_NAME_IN_1(t1)                   MakeRefTuple(arg1)
+#define IPC_NAME_IN_2(t1, t2)               MakeRefTuple(arg1, arg2)
+#define IPC_NAME_IN_3(t1, t2, t3)           MakeRefTuple(arg1, arg2, arg3)
+#define IPC_NAME_IN_4(t1, t2, t3, t4)       MakeRefTuple(arg1, arg2, arg3, arg4)
+#define IPC_NAME_IN_5(t1, t2, t3, t4, t5)   MakeRefTuple(arg1, arg2, arg3, arg4, arg5)
+#define IPC_NAME_IN_6(t1, t2, t3, t4, t5, t6)   MakeRefTuple(arg1, arg2, arg3, arg4, arg5, arg6)
+
+#define IPC_NAME_OUT_0()                    MakeTuple()
+#define IPC_NAME_OUT_1(t1)                  MakeRefTuple(*arg7)
+#define IPC_NAME_OUT_2(t1, t2)              MakeRefTuple(*arg7, *arg8)
+#define IPC_NAME_OUT_3(t1, t2, t3)          MakeRefTuple(*arg7, *arg8, *arg9)
+#define IPC_NAME_OUT_4(t1, t2, t3, t4)      MakeRefTuple(*arg7, *arg8, *arg9, *arg10)
+
+// There are places where the syntax requires a comma if there are input args,
+// if there are input args and output args, or if there are input args or
+// output args.  These macros allow generation of the comma as needed; invoke
+// by token pasting against the argument counts.
+#define IPC_COMMA_0
+#define IPC_COMMA_1 ,
+#define IPC_COMMA_2 ,
+#define IPC_COMMA_3 ,
+#define IPC_COMMA_4 ,
+#define IPC_COMMA_5 ,
+#define IPC_COMMA_6 ,
+
+#define IPC_COMMA_AND_0(x)
+#define IPC_COMMA_AND_1(x) x
+#define IPC_COMMA_AND_2(x) x
+#define IPC_COMMA_AND_3(x) x
+#define IPC_COMMA_AND_4(x) x
+#define IPC_COMMA_AND_5(x) x
+#define IPC_COMMA_AND_6(x) x
+
+#define IPC_COMMA_OR_0(x) x
+#define IPC_COMMA_OR_1(x) ,
+#define IPC_COMMA_OR_2(x) ,
+#define IPC_COMMA_OR_3(x) ,
+#define IPC_COMMA_OR_4(x) ,
+#define IPC_COMMA_OR_5(x) ,
+#define IPC_COMMA_OR_6(x) ,
+
+// Message IDs
+// Note: we currently use __LINE__ to give unique IDs to messages within
+// a file.  They're globally unique since each file defines its own
+// IPC_MESSAGE_START.  Ideally, we wouldn't use line numbers (a possibility
+// is to instead use the __COUNTER__ macro, but it needs gcc 4.3 and xcode
+// doesn't use it yet).
+#define IPC_MESSAGE_ID() ((IPC_MESSAGE_START << 16) + __LINE__)
+#define IPC_MESSAGE_ID_CLASS(id) ((id) >> 16)
+#define IPC_MESSAGE_ID_LINE(id) ((id) & 0xffff)
+
+// Message crackers and handlers.
+// Prefer to use the IPC_BEGIN_MESSAGE_MAP_EX to the older macros since they
+// allow you to detect when a message could not be de-serialized. Usage:
+//
+//   bool MyClass::OnMessageReceived(const IPC::Message& msg) {
+//     bool handled = true;
+//     bool msg_is_good = false;
+//     IPC_BEGIN_MESSAGE_MAP_EX(MyClass, msg, msg_is_good)
+//       IPC_MESSAGE_HANDLER(MsgClassOne, OnMsgClassOne)
+//       ...more handlers here ...
+//       IPC_MESSAGE_HANDLER(MsgClassTen, OnMsgClassTen)
+//       IPC_MESSAGE_UNHANDLED(handled = false)
+//     IPC_END_MESSAGE_MAP_EX()
+//     if (!msg_is_good) {
+//       // Signal error here or terminate offending process.
+//     }
+//     return handled;
+//   }
+
+
+#define IPC_BEGIN_MESSAGE_MAP_EX(class_name, msg, msg_is_ok) \
+  { \
+    typedef class_name _IpcMessageHandlerClass; \
+    const IPC::Message& ipc_message__ = msg; \
+    bool& msg_is_ok__ = msg_is_ok; \
+    switch (ipc_message__.type()) { \
+
+#define IPC_BEGIN_MESSAGE_MAP(class_name, msg) \
+  { \
+    typedef class_name _IpcMessageHandlerClass; \
+    const IPC::Message& ipc_message__ = msg; \
+    bool msg_is_ok__ = true; \
+    switch (ipc_message__.type()) { \
+
+#define IPC_MESSAGE_FORWARD(msg_class, obj, member_func) \
+  case msg_class::ID: \
+    msg_is_ok__ = msg_class::Dispatch(&ipc_message__, obj, this, &member_func); \
+    break;
+
+#define IPC_MESSAGE_FORWARD_EX(msg_class, obj, sender, member_func)    \
+  case msg_class::ID: \
+  msg_is_ok__ = msg_class::Dispatch(&ipc_message__, obj, sender, &member_func); \
+    break;
+
+#define IPC_MESSAGE_HANDLER(msg_class, member_func, sender)                    \
+    IPC_MESSAGE_FORWARD_EX(msg_class, this, sender, _IpcMessageHandlerClass::member_func)
+
+#define IPC_MESSAGE_HANDLER_EX(msg_class, sender, member_func)                 \
+    IPC_MESSAGE_FORWARD_EX(msg_class, this, sender, _IpcMessageHandlerClass::member_func)
+
+#define IPC_MESSAGE_FORWARD_DELAY_REPLY(msg_class, obj, member_func) \
+    case msg_class::ID: \
+    msg_is_ok__ = msg_class::DispatchDelayReply(&ipc_message__, obj, &member_func); \
+    break;
+
+#define IPC_MESSAGE_HANDLER_DELAY_REPLY(msg_class, member_func) \
+  IPC_MESSAGE_FORWARD_DELAY_REPLY(msg_class, this, \
+                                  _IpcMessageHandlerClass::member_func)
+
+#define IPC_MESSAGE_HANDLER_GENERIC(msg_class, code) \
+  case msg_class::ID: \
+    code; \
+    break;
+
+#define IPC_REPLY_HANDLER(func) \
+   case IPC_REPLY_ID: \
+     func(ipc_message__); \
+     break;
+
+
+#define IPC_MESSAGE_UNHANDLED(code) \
+  default: \
+    code; \
+    break;
+
+#define IPC_MESSAGE_UNHANDLED_ERROR() \
+  IPC_MESSAGE_UNHANDLED(NOTREACHED() << \
+                              "Invalid message with type = " << \
+                              ipc_message__.type())
+
+#define IPC_END_MESSAGE_MAP() \
+  } \
+}
+
+#define IPC_END_MESSAGE_MAP_EX() \
+  } \
+}
+
+// This corresponds to an enum value from IPCMessageStart.
+#define IPC_MESSAGE_CLASS(message) \
+  IPC_MESSAGE_ID_CLASS(message.type())
+
+#endif  // IPC_IPC_MESSAGE_MACROS_H_
+
+// Clean up IPC_MESSAGE_START in this unguarded section so that the
+// XXX_messages.h files need not do so themselves.  This makes the
+// XXX_messages.h files easier to write.
+#undef IPC_MESSAGE_START
diff --git a/ipc/ipc_message_null_macros.h b/ipc/ipc_message_null_macros.h
new file mode 100644 (file)
index 0000000..7cd02f5
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.
+
+// No include guard, may be included multiple times.
+
+// NULL out all the macros that need NULLing, so that multiple includes of
+// the XXXX_messages_internal.h files will not generate noise.
+#undef IPC_STRUCT_BEGIN
+#undef IPC_STRUCT_MEMBER
+#undef IPC_STRUCT_END
+#undef IPC_STRUCT_TRAITS_BEGIN
+#undef IPC_STRUCT_TRAITS_MEMBER
+#undef IPC_STRUCT_TRAITS_PARENT
+#undef IPC_STRUCT_TRAITS_END
+#undef IPC_ENUM_TRAITS
+#undef IPC_MESSAGE_DECL
+
+#define IPC_STRUCT_BEGIN(struct_name)
+#define IPC_STRUCT_MEMBER(type, name)
+#define IPC_STRUCT_END()
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name)
+#define IPC_STRUCT_TRAITS_MEMBER(name)
+#define IPC_STRUCT_TRAITS_PARENT(type)
+#define IPC_STRUCT_TRAITS_END()
+#define IPC_ENUM_TRAITS(enum_name)
+#define IPC_MESSAGE_DECL(sync, kind, msg_class, \
+                         in_cnt, out_cnt, in_list, out_list)
+
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc
new file mode 100644 (file)
index 0000000..2e3f042
--- /dev/null
@@ -0,0 +1,485 @@
+// 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 "ipc/ipc_message_utils.h"
+
+//#include "base/file_path.h"
+//#include "base/json/json_writer.h"
+//#include "base/memory/scoped_ptr.h"
+//#include "base/nullable_string16.h"
+#include "base/string_number_conversions.h"
+#include "base/time.h"
+//#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#if defined(OS_POSIX)
+//#include "ipc/file_descriptor_set_posix.h"
+#endif
+//#include "ipc/ipc_channel_handle.h"
+
+namespace IPC {
+
+const int kMaxRecursionDepth = 100;
+
+// Value serialization
+
+/*
+static bool ReadValue(const Message* m, void** iter, Value** value,
+                      int recursion);
+
+static void WriteValue(Message* m, const Value* value, int recursion) {
+  if (recursion > kMaxRecursionDepth) {
+    LOG(WARNING) << "Max recursion depth hit in WriteValue.";
+    return;
+  }
+
+  m->WriteInt(value->GetType());
+
+  switch (value->GetType()) {
+    case Value::TYPE_NULL:
+    break;
+    case Value::TYPE_BOOLEAN: {
+      bool val;
+      value->GetAsBoolean(&val);
+      WriteParam(m, val);
+      break;
+    }
+    case Value::TYPE_INTEGER: {
+      int val;
+      value->GetAsInteger(&val);
+      WriteParam(m, val);
+      break;
+    }
+    case Value::TYPE_DOUBLE: {
+      double val;
+      value->GetAsDouble(&val);
+      WriteParam(m, val);
+      break;
+    }
+    case Value::TYPE_STRING: {
+      std::string val;
+      value->GetAsString(&val);
+      WriteParam(m, val);
+      break;
+    }
+    case Value::TYPE_BINARY: {
+      const base::BinaryValue* binary =
+          static_cast<const base::BinaryValue*>(value);
+      m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
+      break;
+    }
+    case Value::TYPE_DICTIONARY: {
+      const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
+
+      WriteParam(m, static_cast<int>(dict->size()));
+
+      for (DictionaryValue::key_iterator it = dict->begin_keys();
+           it != dict->end_keys(); ++it) {
+        Value* subval;
+        if (dict->GetWithoutPathExpansion(*it, &subval)) {
+          WriteParam(m, *it);
+          WriteValue(m, subval, recursion + 1);
+        } else {
+          NOTREACHED() << "DictionaryValue iterators are filthy liars.";
+        }
+      }
+      break;
+    }
+    case Value::TYPE_LIST: {
+      const ListValue* list = static_cast<const ListValue*>(value);
+      WriteParam(m, static_cast<int>(list->GetSize()));
+      for (size_t i = 0; i < list->GetSize(); ++i) {
+        Value* subval;
+        if (list->Get(i, &subval)) {
+          WriteValue(m, subval, recursion + 1);
+        } else {
+          NOTREACHED() << "ListValue::GetSize is a filthy liar.";
+        }
+      }
+      break;
+    }
+  }
+}
+
+// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
+// object.
+static bool ReadDictionaryValue(const Message* m, void** iter,
+                                DictionaryValue* value, int recursion) {
+  int size;
+  if (!ReadParam(m, iter, &size))
+    return false;
+
+  for (int i = 0; i < size; ++i) {
+    std::string key;
+    Value* subval;
+    if (!ReadParam(m, iter, &key) ||
+        !ReadValue(m, iter, &subval, recursion + 1))
+      return false;
+    value->Set(key, subval);
+  }
+
+  return true;
+}
+
+// Helper for ReadValue that reads a ReadListValue into a pre-allocated
+// object.
+static bool ReadListValue(const Message* m, void** iter,
+                          ListValue* value, int recursion) {
+  int size;
+  if (!ReadParam(m, iter, &size))
+    return false;
+
+  for (int i = 0; i < size; ++i) {
+    Value* subval;
+    if (!ReadValue(m, iter, &subval, recursion + 1))
+      return false;
+    value->Set(i, subval);
+  }
+
+  return true;
+}
+
+static bool ReadValue(const Message* m, void** iter, Value** value,
+                      int recursion) {
+  if (recursion > kMaxRecursionDepth) {
+    LOG(WARNING) << "Max recursion depth hit in ReadValue.";
+    return false;
+  }
+
+  int type;
+  if (!ReadParam(m, iter, &type))
+    return false;
+
+  switch (type) {
+    case Value::TYPE_NULL:
+    *value = Value::CreateNullValue();
+    break;
+    case Value::TYPE_BOOLEAN: {
+      bool val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = Value::CreateBooleanValue(val);
+      break;
+    }
+    case Value::TYPE_INTEGER: {
+      int val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = Value::CreateIntegerValue(val);
+      break;
+    }
+    case Value::TYPE_DOUBLE: {
+      double val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = Value::CreateDoubleValue(val);
+      break;
+    }
+    case Value::TYPE_STRING: {
+      std::string val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = Value::CreateStringValue(val);
+      break;
+    }
+    case Value::TYPE_BINARY: {
+      const char* data;
+      int length;
+      if (!m->ReadData(iter, &data, &length))
+        return false;
+      *value = base::BinaryValue::CreateWithCopiedBuffer(data, length);
+      break;
+    }
+    case Value::TYPE_DICTIONARY: {
+      scoped_ptr<DictionaryValue> val(new DictionaryValue());
+      if (!ReadDictionaryValue(m, iter, val.get(), recursion))
+        return false;
+      *value = val.release();
+      break;
+    }
+    case Value::TYPE_LIST: {
+      scoped_ptr<ListValue> val(new ListValue());
+      if (!ReadListValue(m, iter, val.get(), recursion))
+        return false;
+      *value = val.release();
+      break;
+    }
+    default:
+    return false;
+  }
+
+  return true;
+}
+*/
+
+void ParamTraits<int>::Log(const param_type& p, std::string* l) {
+  //l->append(base::IntToString(p));
+}
+
+void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
+  //l->append(base::UintToString(p));
+}
+
+void ParamTraits<long>::Log(const param_type& p, std::string* l) {
+  //l->append(base::Int64ToString(static_cast<int64>(p)));
+}
+
+void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
+  //l->append(base::Uint64ToString(static_cast<uint64>(p)));
+}
+
+void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
+  //l->append(base::Int64ToString(static_cast<int64>(p)));
+}
+
+void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
+  //l->append(base::Uint64ToString(p));
+}
+
+
+void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
+  m->WriteBytes(&p, sizeof(param_type));
+}
+
+bool ParamTraits<unsigned short>::Read(const Message* m, void** iter,
+                                       param_type* r) {
+  const char* data;
+  if (!m->ReadBytes(iter, &data, sizeof(param_type)))
+    return false;
+  memcpy(r, data, sizeof(param_type));
+  return true;
+}
+
+/*
+void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
+  l->append(base::UintToString(p));
+}
+
+
+void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
+  ParamTraits<int64>::Write(m, p.ToInternalValue());
+}
+
+bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
+                                   param_type* r) {
+  int64 value;
+  if (!ParamTraits<int64>::Read(m, iter, &value))
+    return false;
+  *r = base::Time::FromInternalValue(value);
+  return true;
+}
+
+void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
+  ParamTraits<int64>::Log(p.ToInternalValue(), l);
+}
+
+void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
+  ParamTraits<int64> ::Write(m, p.InMicroseconds());
+}
+
+bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
+                                         void** iter,
+                                         param_type* r) {
+  int64 value;
+  bool ret = ParamTraits<int64> ::Read(m, iter, &value);
+  if (ret)
+    *r = base::TimeDelta::FromMicroseconds(value);
+
+  return ret;
+}
+
+void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
+  ParamTraits<int64> ::Log(p.InMicroseconds(), l);
+}
+
+void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
+  WriteValue(m, &p, 0);
+}
+
+bool ParamTraits<DictionaryValue>::Read(
+    const Message* m, void** iter, param_type* r) {
+  int type;
+  if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
+    return false;
+
+  return ReadDictionaryValue(m, iter, r, 0);
+}
+
+void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
+  std::string json;
+  base::JSONWriter::Write(&p, false, &json);
+  l->append(json);
+}
+
+void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
+  WriteValue(m, &p, 0);
+}
+
+bool ParamTraits<ListValue>::Read(
+    const Message* m, void** iter, param_type* r) {
+  int type;
+  if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
+    return false;
+
+  return ReadListValue(m, iter, r, 0);
+}
+
+void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
+  std::string json;
+  base::JSONWriter::Write(&p, false, &json);
+  l->append(json);
+}
+
+void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
+  l->append(WideToUTF8(p));
+}
+
+void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
+  WriteParam(m, p.string());
+  WriteParam(m, p.is_null());
+}
+
+bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
+                                         param_type* r) {
+  string16 string;
+  if (!ReadParam(m, iter, &string))
+    return false;
+  bool is_null;
+  if (!ReadParam(m, iter, &is_null))
+    return false;
+  *r = NullableString16(string, is_null);
+  return true;
+}
+
+void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
+  l->append("(");
+  LogParam(p.string(), l);
+  l->append(", ");
+  LogParam(p.is_null(), l);
+  l->append(")");
+}
+
+#if !defined(WCHAR_T_IS_UTF16)
+void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
+  l->append(UTF16ToUTF8(p));
+}
+#endif
+
+*/
+
+/*
+void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
+  ParamTraits<FilePath::StringType>::Write(m, p.value());
+}
+
+bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
+  FilePath::StringType value;
+  if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
+    return false;
+  *r = FilePath(value);
+  return true;
+}
+
+void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
+  ParamTraits<FilePath::StringType>::Log(p.value(), l);
+}
+
+#if defined(OS_POSIX)
+void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
+  const bool valid = p.fd >= 0;
+  WriteParam(m, valid);
+
+  if (valid) {
+    if (!m->WriteFileDescriptor(p))
+      NOTREACHED();
+  }
+}
+
+bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
+                                             param_type* r) {
+  bool valid;
+  if (!ReadParam(m, iter, &valid))
+    return false;
+
+  if (!valid) {
+    r->fd = -1;
+    r->auto_close = false;
+    return true;
+  }
+
+  return m->ReadFileDescriptor(iter, r);
+}
+
+void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
+                                            std::string* l) {
+  if (p.auto_close) {
+    l->append(StringPrintf("FD(%d auto-close)", p.fd));
+  } else {
+    l->append(StringPrintf("FD(%d)", p.fd));
+  }
+}
+#endif  // defined(OS_POSIX)
+
+void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
+  WriteParam(m, p.name);
+#if defined(OS_POSIX)
+  WriteParam(m, p.socket);
+#endif
+}
+
+bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
+                                           param_type* r) {
+  return ReadParam(m, iter, &r->name)
+#if defined(OS_POSIX)
+      && ReadParam(m, iter, &r->socket)
+#endif
+      ;
+}
+
+void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
+                                          std::string* l) {
+  l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
+#if defined(OS_POSIX)
+  ParamTraits<base::FileDescriptor>::Log(p.socket, l);
+#endif
+  l->append(")");
+}
+
+LogData::LogData()
+    : routing_id(0),
+      type(0),
+      sent(0),
+      receive(0),
+      dispatch(0) {
+}
+
+LogData::~LogData() {
+}
+
+void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
+  WriteParam(m, p.channel);
+  WriteParam(m, p.routing_id);
+  WriteParam(m, static_cast<int>(p.type));
+  WriteParam(m, p.flags);
+  WriteParam(m, p.sent);
+  WriteParam(m, p.receive);
+  WriteParam(m, p.dispatch);
+  WriteParam(m, p.params);
+}
+
+bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
+  int type = -1;
+  bool result =
+      ReadParam(m, iter, &r->channel) &&
+      ReadParam(m, iter, &r->routing_id) &&
+      ReadParam(m, iter, &type) &&
+      ReadParam(m, iter, &r->flags) &&
+      ReadParam(m, iter, &r->sent) &&
+      ReadParam(m, iter, &r->receive) &&
+      ReadParam(m, iter, &r->dispatch) &&
+      ReadParam(m, iter, &r->params);
+  r->type = static_cast<uint16>(type);
+  return result;
+}
+*/
+}  // namespace IPC
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
new file mode 100755 (executable)
index 0000000..3b5ff6f
--- /dev/null
@@ -0,0 +1,1248 @@
+// 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 IPC_IPC_MESSAGE_UTILS_H_
+#define IPC_IPC_MESSAGE_UTILS_H_
+#pragma once
+
+#include <algorithm>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+//#include "base/format_macros.h"
+//#include "base/string16.h"
+//#include "base/stringprintf.h"
+//#include "base/string_util.h"
+#include "base/tuple.h"
+#include "ipc/ipc_param_traits.h"
+#include "ipc/ipc_sync_message.h"
+
+#if defined(COMPILER_GCC)
+// GCC "helpfully" tries to inline template methods in release mode. Except we
+// want the majority of the template junk being expanded once in the
+// implementation file (and only provide the definitions in
+// ipc_message_utils_impl.h in those files) and exported, instead of expanded
+// at every call site. Special note: GCC happily accepts the attribute before
+// the method declaration, but only acts on it if it is after.
+#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
+// Starting in gcc 4.5, the noinline no longer implies the concept covered by
+// the introduced noclone attribute, which will create specialized versions of
+// functions/methods when certain types are constant.
+// www.gnu.org/software/gcc/gcc-4.5/changes.html
+#define IPC_MSG_NOINLINE  __attribute__((noinline, noclone));
+#else
+#define IPC_MSG_NOINLINE  __attribute__((noinline));
+#endif
+#elif defined(COMPILER_MSVC)
+// MSVC++ doesn't do this.
+#define IPC_MSG_NOINLINE
+#else
+#error "Please add the noinline property for your new compiler here."
+#endif
+
+// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
+// base.  Messages have unique IDs across channels in order for the IPC logging
+// code to figure out the message class from its ID.
+enum IPCMessageStart {
+  AutomationMsgStart = 0,
+  CmcStrRegistryManagerStart,
+  LastIPCMsgStart
+};
+
+class FilePath;
+class NullableString16;
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+class Time;
+class TimeDelta;
+struct FileDescriptor;
+}
+
+namespace IPC {
+
+struct ChannelHandle;
+
+//-----------------------------------------------------------------------------
+// An iterator class for reading the fields contained within a Message.
+
+class MessageIterator {
+ public:
+  explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
+  }
+  int NextInt() const {
+    int val = -1;
+    if (!msg_.ReadInt(&iter_, &val))
+      NOTREACHED();
+    return val;
+  }
+/*
+  const std::string NextString() const {
+    std::string val;
+    if (!msg_.ReadString(&iter_, &val))
+      NOTREACHED();
+    return val;
+  }
+  const std::wstring NextWString() const {
+    std::wstring val;
+    if (!msg_.ReadWString(&iter_, &val))
+      NOTREACHED();
+    return val;
+  }
+*/
+  void NextData(const char** data, int* length) const {
+    if (!msg_.ReadData(&iter_, data, length)) {
+      NOTREACHED();
+    }
+  }
+ private:
+  const Message& msg_;
+  mutable void* iter_;
+};
+
+//-----------------------------------------------------------------------------
+// A dummy struct to place first just to allow leading commas for all
+// members in the macro-generated constructor initializer lists.
+struct NoParams {
+};
+
+//-----------------------------------------------------------------------------
+// ParamTraits specializations, etc.
+
+template <class P>
+static inline void WriteParam(Message* m, const P& p) {
+  typedef typename SimilarTypeTraits<P>::Type Type;
+  ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
+}
+
+template <class P>
+static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
+                                                P* p) {
+  typedef typename SimilarTypeTraits<P>::Type Type;
+  return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
+}
+
+
+template <class P>
+static inline void LogParam(const P& p, std::string* l) {
+  typedef typename SimilarTypeTraits<P>::Type Type;
+  ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
+}
+
+
+template <>
+struct ParamTraits<bool> {
+  typedef bool param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteBool(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadBool(iter, r);
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append(p ? "true" : "false");
+  }
+};
+
+template <>
+struct ParamTraits<int> {
+  typedef int param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteInt(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadInt(iter, r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned int> {
+  typedef unsigned int param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteInt(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadInt(iter, reinterpret_cast<int*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<long> {
+  typedef long param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteLong(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadLong(iter, r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned long> {
+  typedef unsigned long param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteLong(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadLong(iter, reinterpret_cast<long*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<long long> {
+  typedef long long param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteInt64(static_cast<int64>(p));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned long long> {
+  typedef unsigned long long param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteInt64(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<unsigned short> {
+  typedef unsigned short param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+// Note that the IPC layer doesn't sanitize NaNs and +/- INF values.  Clients
+// should be sure to check the sanity of these values after receiving them over
+// IPC.
+template <>
+struct ParamTraits<float> {
+  typedef float param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    const char *data;
+    int data_size;
+    if (!m->ReadData(iter, &data, &data_size) ||
+        data_size != sizeof(param_type)) {
+      NOTREACHED();
+      return false;
+    }
+    memcpy(r, data, sizeof(param_type));
+    return true;
+  }
+
+  static void Log(const param_type& p, std::string* l) {
+      //l->append(StringPrintf("%e", p));
+  }
+
+};
+
+template <>
+struct ParamTraits<double> {
+  typedef double param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    const char *data;
+    int data_size;
+    if (!m->ReadData(iter, &data, &data_size) ||
+        data_size != sizeof(param_type)) {
+      NOTREACHED();
+      return false;
+    }
+    memcpy(r, data, sizeof(param_type));
+    return true;
+  }
+
+  static void Log(const param_type& p, std::string* l) {
+      //l->append(StringPrintf("%e", p));
+  }
+
+};
+
+/*
+template <>
+struct IPC_EXPORT ParamTraits<base::Time> {
+  typedef base::Time param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::TimeDelta> {
+  typedef base::TimeDelta param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+#if defined(OS_WIN)
+template <>
+struct ParamTraits<LOGFONT> {
+  typedef LOGFONT param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    const char *data;
+    int data_size = 0;
+    bool result = m->ReadData(iter, &data, &data_size);
+    if (result && data_size == sizeof(LOGFONT)) {
+      memcpy(r, data, sizeof(LOGFONT));
+    } else {
+      result = false;
+      NOTREACHED();
+    }
+
+    return result;
+  }
+  static void Log(const param_type& p, std::string* l) {
+//    l->append(StringPrintf("<LOGFONT>"));
+  }
+};
+
+template <>
+struct ParamTraits<MSG> {
+  typedef MSG param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    const char *data;
+    int data_size = 0;
+    bool result = m->ReadData(iter, &data, &data_size);
+    if (result && data_size == sizeof(MSG)) {
+      memcpy(r, data, sizeof(MSG));
+    } else {
+      result = false;
+      NOTREACHED();
+    }
+
+    return result;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("<MSG>");
+  }
+};
+#endif  // defined(OS_WIN)
+
+template <>
+struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
+  typedef base::DictionaryValue param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::ListValue> {
+  typedef base::ListValue param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+*/
+template <>
+struct ParamTraits<std::string> {
+  typedef std::string param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteString(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadString(iter, r);
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append(p);
+  }
+};
+
+/*
+template<typename CharType>
+static void LogBytes(const std::vector<CharType>& data, std::string* out) {
+#if defined(OS_WIN)
+  // Windows has a GUI for logging, which can handle arbitrary binary data.
+  for (size_t i = 0; i < data.size(); ++i)
+    out->push_back(data[i]);
+#else
+  // On POSIX, we log to stdout, which we assume can display ASCII.
+  static const size_t kMaxBytesToLog = 100;
+  for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
+    if (isprint(data[i]))
+      out->push_back(data[i]);
+    else
+    {
+       // out->append(StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
+    }
+  }
+  if (data.size() > kMaxBytesToLog) {
+//    out->append(
+//        StringPrintf(" and %u more bytes",
+//                     static_cast<unsigned>(data.size() - kMaxBytesToLog)));
+  }
+#endif
+}
+*/
+
+template <>
+struct ParamTraits<std::vector<unsigned char> > {
+  typedef std::vector<unsigned char> param_type;
+  static void Write(Message* m, const param_type& p) {
+    if (p.empty()) {
+      m->WriteData(NULL, 0);
+    } else {
+      m->WriteData(reinterpret_cast<const char*>(&p.front()),
+                   static_cast<int>(p.size()));
+    }
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    const char *data;
+    int data_size = 0;
+    if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
+      return false;
+    r->resize(data_size);
+    if (data_size)
+      memcpy(&r->front(), data, data_size);
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+      // LogBytes(p, l);
+  }
+};
+
+template <>
+struct ParamTraits<std::vector<char> > {
+  typedef std::vector<char> param_type;
+  static void Write(Message* m, const param_type& p) {
+    if (p.empty()) {
+      m->WriteData(NULL, 0);
+    } else {
+      m->WriteData(&p.front(), static_cast<int>(p.size()));
+    }
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    const char *data;
+    int data_size = 0;
+    if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
+      return false;
+    r->resize(data_size);
+    if (data_size)
+      memcpy(&r->front(), data, data_size);
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+      //LogBytes(p, l);
+  }
+};
+
+template <class P>
+struct ParamTraits<std::vector<P> > {
+  typedef std::vector<P> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    for (size_t i = 0; i < p.size(); i++)
+      WriteParam(m, p[i]);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    int size;
+    // ReadLength() checks for < 0 itself.
+    if (!m->ReadLength(iter, &size))
+      return false;
+    // Resizing beforehand is not safe, see BUG 1006367 for details.
+    if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
+      return false;
+    r->resize(size);
+    for (int i = 0; i < size; i++) {
+      if (!ReadParam(m, iter, &(*r)[i]))
+        return false;
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+//    for (size_t i = 0; i < p.size(); ++i) {
+//      if (i != 0)
+//        l->append(" ");
+//      LogParam((p[i]), l);
+//    }
+  }
+};
+
+/*
+template <class P>
+struct ParamTraits<std::set<P> > {
+  typedef std::set<P> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter)
+      WriteParam(m, *iter);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    int size;
+    if (!m->ReadLength(iter, &size))
+      return false;
+    for (int i = 0; i < size; ++i) {
+      P item;
+      if (!ReadParam(m, iter, &item))
+        return false;
+      r->insert(item);
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("<std::set>");
+  }
+};
+
+
+template <class K, class V>
+struct ParamTraits<std::map<K, V> > {
+  typedef std::map<K, V> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter) {
+      WriteParam(m, iter->first);
+      WriteParam(m, iter->second);
+    }
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    int size;
+    if (!ReadParam(m, iter, &size) || size < 0)
+      return false;
+    for (int i = 0; i < size; ++i) {
+      K k;
+      if (!ReadParam(m, iter, &k))
+        return false;
+      V& value = (*r)[k];
+      if (!ReadParam(m, iter, &value))
+        return false;
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("<std::map>");
+  }
+};
+
+
+template <>
+struct ParamTraits<std::wstring> {
+  typedef std::wstring param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteWString(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadWString(iter, r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <class A, class B>
+struct ParamTraits<std::pair<A, B> > {
+  typedef std::pair<A, B> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.first);
+    WriteParam(m, p.second);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("(");
+    LogParam(p.first, l);
+    l->append(", ");
+    LogParam(p.second, l);
+    l->append(")");
+  }
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<NullableString16> {
+  typedef NullableString16 param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
+// need this trait.
+#if !defined(WCHAR_T_IS_UTF16)
+template <>
+struct ParamTraits<string16> {
+  typedef string16 param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteString16(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadString16(iter, r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+#endif
+
+// and, a few more useful types...
+#if defined(OS_WIN)
+template <>
+struct ParamTraits<HANDLE> {
+  typedef HANDLE param_type;
+  static void Write(Message* m, const param_type& p) {
+    // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
+    // bit systems.
+    m->WriteUInt32(reinterpret_cast<uint32>(p));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    DCHECK_EQ(sizeof(param_type), sizeof(uint32));
+    return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
+  }
+  static void Log(const param_type& p, std::string* l) {
+//    l->append(StringPrintf("0x%X", p));
+  }
+};
+
+template <>
+struct ParamTraits<HCURSOR> {
+  typedef HCURSOR param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteUInt32(reinterpret_cast<uint32>(p));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    DCHECK_EQ(sizeof(param_type), sizeof(uint32));
+    return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
+  }
+  static void Log(const param_type& p, std::string* l) {
+//    l->append(StringPrintf("0x%X", p));
+  }
+};
+
+template <>
+struct ParamTraits<HACCEL> {
+  typedef HACCEL param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteUInt32(reinterpret_cast<uint32>(p));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    DCHECK_EQ(sizeof(param_type), sizeof(uint32));
+    return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
+  }
+};
+
+template <>
+struct ParamTraits<POINT> {
+  typedef POINT param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteInt(p.x);
+    m->WriteInt(p.y);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    int x, y;
+    if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
+      return false;
+    r->x = x;
+    r->y = y;
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+//    l->append(StringPrintf("(%d, %d)", p.x, p.y));
+  }
+};
+#endif  // defined(OS_WIN)
+
+template <>
+struct IPC_EXPORT ParamTraits<FilePath> {
+  typedef FilePath param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+#if defined(OS_POSIX)
+// FileDescriptors may be serialised over IPC channels on POSIX. On the
+// receiving side, the FileDescriptor is a valid duplicate of the file
+// descriptor which was transmitted: *it is not just a copy of the integer like
+// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
+// this case, the receiving end will see a value of -1. *Zero is a valid file
+// descriptor*.
+//
+// The received file descriptor will have the |auto_close| flag set to true. The
+// code which handles the message is responsible for taking ownership of it.
+// File descriptors are OS resources and must be closed when no longer needed.
+//
+// When sending a file descriptor, the file descriptor must be valid at the time
+// of transmission. Since transmission is not synchronous, one should consider
+// dup()ing any file descriptors to be transmitted and setting the |auto_close|
+// flag, which causes the file descriptor to be closed after writing.
+template<>
+struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
+  typedef base::FileDescriptor param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+#endif  // defined(OS_POSIX)
+
+// A ChannelHandle is basically a platform-inspecific wrapper around the
+// fact that IPC endpoints are handled specially on POSIX.  See above comments
+// on FileDescriptor for more background.
+template<>
+struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
+  typedef ChannelHandle param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+#if defined(OS_WIN)
+template <>
+struct ParamTraits<XFORM> {
+  typedef XFORM param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    const char *data;
+    int data_size = 0;
+    bool result = m->ReadData(iter, &data, &data_size);
+    if (result && data_size == sizeof(XFORM)) {
+      memcpy(r, data, sizeof(XFORM));
+    } else {
+      result = false;
+      NOTREACHED();
+    }
+
+    return result;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("<XFORM>");
+  }
+};
+#endif  // defined(OS_WIN)
+
+struct IPC_EXPORT LogData {
+  LogData();
+  ~LogData();
+
+  std::string channel;
+  int32 routing_id;
+  uint32 type;  // "User-defined" message type, from ipc_message.h.
+  std::string flags;
+  int64 sent;  // Time that the message was sent (i.e. at Send()).
+  int64 receive;  // Time before it was dispatched (i.e. before calling
+                  // OnMessageReceived).
+  int64 dispatch;  // Time after it was dispatched (i.e. after calling
+                   // OnMessageReceived).
+  std::string message_name;
+  std::string params;
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<LogData> {
+  typedef LogData param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l) {
+    // Doesn't make sense to implement this!
+  }
+};
+
+*/
+template <>
+struct ParamTraits<Message> {
+  static void Write(Message* m, const Message& p) {
+    DCHECK(p.size() <= INT_MAX);
+    int message_size = static_cast<int>(p.size());
+    m->WriteInt(message_size);
+    m->WriteData(reinterpret_cast<const char*>(p.data()), message_size);
+  }
+  static bool Read(const Message* m, void** iter, Message* r) {
+    int size;
+    if (!m->ReadInt(iter, &size))
+      return false;
+    const char* data;
+    if (!m->ReadData(iter, &data, &size))
+      return false;
+    *r = Message(data, size);
+    return true;
+  }
+  static void Log(const Message& p, std::string* l) {
+    l->append("<IPC::Message>");
+  }
+};
+
+template <>
+struct ParamTraits<Tuple0> {
+  typedef Tuple0 param_type;
+  static void Write(Message* m, const param_type& p) {
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+  }
+};
+
+template <class A>
+struct ParamTraits< Tuple1<A> > {
+  typedef Tuple1<A> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.a);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return ReadParam(m, iter, &r->a);
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(p.a, l);
+  }
+};
+
+template <class A, class B>
+struct ParamTraits< Tuple2<A, B> > {
+  typedef Tuple2<A, B> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.a);
+    WriteParam(m, p.b);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return (ReadParam(m, iter, &r->a) &&
+            ReadParam(m, iter, &r->b));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(p.a, l);
+    l->append(", ");
+    LogParam(p.b, l);
+  }
+};
+
+template <class A, class B, class C>
+struct ParamTraits< Tuple3<A, B, C> > {
+  typedef Tuple3<A, B, C> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.a);
+    WriteParam(m, p.b);
+    WriteParam(m, p.c);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return (ReadParam(m, iter, &r->a) &&
+            ReadParam(m, iter, &r->b) &&
+            ReadParam(m, iter, &r->c));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(p.a, l);
+    l->append(", ");
+    LogParam(p.b, l);
+    l->append(", ");
+    LogParam(p.c, l);
+  }
+};
+
+template <class A, class B, class C, class D>
+struct ParamTraits< Tuple4<A, B, C, D> > {
+  typedef Tuple4<A, B, C, D> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.a);
+    WriteParam(m, p.b);
+    WriteParam(m, p.c);
+    WriteParam(m, p.d);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return (ReadParam(m, iter, &r->a) &&
+            ReadParam(m, iter, &r->b) &&
+            ReadParam(m, iter, &r->c) &&
+            ReadParam(m, iter, &r->d));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(p.a, l);
+    l->append(", ");
+    LogParam(p.b, l);
+    l->append(", ");
+    LogParam(p.c, l);
+    l->append(", ");
+    LogParam(p.d, l);
+  }
+};
+
+template <class A, class B, class C, class D, class E>
+struct ParamTraits< Tuple5<A, B, C, D, E> > {
+  typedef Tuple5<A, B, C, D, E> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.a);
+    WriteParam(m, p.b);
+    WriteParam(m, p.c);
+    WriteParam(m, p.d);
+    WriteParam(m, p.e);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return (ReadParam(m, iter, &r->a) &&
+            ReadParam(m, iter, &r->b) &&
+            ReadParam(m, iter, &r->c) &&
+            ReadParam(m, iter, &r->d) &&
+            ReadParam(m, iter, &r->e));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(p.a, l);
+    l->append(", ");
+    LogParam(p.b, l);
+    l->append(", ");
+    LogParam(p.c, l);
+    l->append(", ");
+    LogParam(p.d, l);
+    l->append(", ");
+    LogParam(p.e, l);
+  }
+};
+
+template <class A, class B, class C, class D, class E, class F>
+struct ParamTraits< Tuple6<A, B, C, D, E, F> > {
+typedef Tuple6<A, B, C, D, E, F> param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.a);
+    WriteParam(m, p.b);
+    WriteParam(m, p.c);
+    WriteParam(m, p.d);
+    WriteParam(m, p.e);
+    WriteParam(m, p.f);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return (ReadParam(m, iter, &r->a) &&
+            ReadParam(m, iter, &r->b) &&
+            ReadParam(m, iter, &r->c) &&
+            ReadParam(m, iter, &r->d) &&
+            ReadParam(m, iter, &r->e) &&
+            ReadParam(m, iter, &r->f));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(p.a, l);
+    l->append(", ");
+    LogParam(p.b, l);
+    l->append(", ");
+    LogParam(p.c, l);
+    l->append(", ");
+    LogParam(p.d, l);
+    l->append(", ");
+    LogParam(p.e, l);
+    l->append(", ");
+    LogParam(p.f, l);
+  }
+};
+
+//-----------------------------------------------------------------------------
+// Generic message subclasses
+
+// Used for asynchronous messages.
+template <class ParamType>
+class __attribute__((visibility("default"))) MessageWithTuple : public Message {
+ public:
+  typedef ParamType Param;
+  typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
+
+  // The constructor and the Read() method's templated implementations are in
+  // ipc_message_utils_impl.h. The subclass constructor and Log() methods call
+  // the templated versions of these and make sure there are instantiations in
+  // those translation units.
+  MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p);
+
+  static bool Read(const Message* msg, Param* p)
+  { // Put definition into class so that Dispatch method could use it.
+    void* iter = NULL;
+    if (ReadParam(msg, &iter, p))
+      return true;
+    NOTREACHED() << "Error deserializing message " << msg->type();
+    return false;
+  } IPC_MSG_NOINLINE;
+
+  // Generic dispatcher.  Should cover most cases.
+  template<class T, class S, class Method>
+  static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {
+    Param p;
+    if (Read(msg, &p)) {
+      DispatchToMethod(obj, func, p);
+      return true;
+    }
+    return false;
+  }
+
+  // The following dispatchers exist for the case where the callback function
+  // needs the message as well.  They assume that "Param" is a type of Tuple
+  // (except the one arg case, as there is no Tuple1).
+  template<class T, class S, typename TA>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)(const Message&, TA)) {
+    Param p;
+    if (Read(msg, &p)) {
+      (obj->*func)(*msg, p.a);
+      return true;
+    }
+    return false;
+  }
+
+  template<class T, class S, typename TA, typename TB>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)(const Message&, TA, TB)) {
+    Param p;
+    if (Read(msg, &p)) {
+      (obj->*func)(*msg, p.a, p.b);
+      return true;
+    }
+    return false;
+  }
+
+  template<class T, class S, typename TA, typename TB, typename TC>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)(const Message&, TA, TB, TC)) {
+    Param p;
+    if (Read(msg, &p)) {
+      (obj->*func)(*msg, p.a, p.b, p.c);
+      return true;
+    }
+    return false;
+  }
+
+  template<class T, class S, typename TA, typename TB, typename TC, typename TD>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)(const Message&, TA, TB, TC, TD)) {
+    Param p;
+    if (Read(msg, &p)) {
+      (obj->*func)(*msg, p.a, p.b, p.c, p.d);
+      return true;
+    }
+    return false;
+  }
+
+  template<class T, class S, typename TA, typename TB, typename TC, typename TD,
+           typename TE>
+  static bool Dispatch(const Message* msg, T* obj, S* sender,
+                       void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
+    Param p;
+    if (Read(msg, &p)) {
+      (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
+      return true;
+    }
+    return false;
+  }
+
+  // Functions used to do manual unpacking.  Only used by the automation code,
+  // these should go away once that code uses SyncChannel.
+  template<typename TA, typename TB>
+  static bool Read(const IPC::Message* msg, TA* a, TB* b) {
+    ParamType params;
+    if (!Read(msg, &params))
+      return false;
+    *a = params.a;
+    *b = params.b;
+    return true;
+  }
+
+  template<typename TA, typename TB, typename TC>
+  static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
+    ParamType params;
+    if (!Read(msg, &params))
+      return false;
+    *a = params.a;
+    *b = params.b;
+    *c = params.c;
+    return true;
+  }
+
+  template<typename TA, typename TB, typename TC, typename TD>
+  static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
+    ParamType params;
+    if (!Read(msg, &params))
+      return false;
+    *a = params.a;
+    *b = params.b;
+    *c = params.c;
+    *d = params.d;
+    return true;
+  }
+
+  template<typename TA, typename TB, typename TC, typename TD, typename TE>
+  static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
+    ParamType params;
+    if (!Read(msg, &params))
+      return false;
+    *a = params.a;
+    *b = params.b;
+    *c = params.c;
+    *d = params.d;
+    *e = params.e;
+    return true;
+  }
+};
+
+// defined in ipc_logging.cc
+IPC_EXPORT void GenerateLogData(const std::string& channel,
+                                const Message& message,
+                                LogData* data);
+
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
+  const std::string& output_params = msg->output_params();
+  if (!l->empty() && !output_params.empty())
+    l->append(", ");
+
+  l->append(output_params);
+}
+
+template <class ReplyParamType>
+inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
+                                    const Message* msg) {
+  if (msg->received_time() != 0) {
+    std::string output_params;
+    LogParam(reply_params, &output_params);
+    msg->set_output_params(output_params);
+  }
+}
+
+inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
+  if (msg->sent_time()) {
+    // Don't log the sync message after dispatch, as we don't have the
+    // output parameters at that point.  Instead, save its data and log it
+    // with the outgoing reply message when it's sent.
+    LogData* data = new LogData;
+    GenerateLogData("", *msg, data);
+    msg->set_dont_log();
+    reply->set_sync_log_data(data);
+  }
+}
+#else
+inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
+
+template <class ReplyParamType>
+inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
+                                    const Message* msg) {}
+
+inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
+#endif
+
+// This class assumes that its template argument is a RefTuple (a Tuple with
+// reference elements). This would go into ipc_message_utils_impl.h, but it is
+// also used by chrome_frame.
+template <class RefTuple>
+class ParamDeserializer : public MessageReplyDeserializer {
+ public:
+  explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
+
+  bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
+    return ReadParam(&msg, &iter, &out_);
+  }
+
+  RefTuple out_;
+};
+
+// Used for synchronous messages.
+template <class SendParamType, class ReplyParamType>
+class __attribute__((visibility("default"))) MessageWithReply : public SyncMessage {
+ public:
+  typedef SendParamType SendParam;
+  typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
+  typedef ReplyParamType ReplyParam;
+
+  MessageWithReply(int32 routing_id, uint32 type,
+                   const RefSendParam& send, const ReplyParam& reply);
+  static bool ReadSendParam(const Message* msg, SendParam* p)
+  { // Put definition into class so that Dispatch method could use it.
+    void* iter = SyncMessage::GetDataIterator(msg);
+    return ReadParam(msg, &iter, p);
+  } IPC_MSG_NOINLINE;
+  static bool ReadReplyParam(
+      const Message* msg,
+      typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
+
+  template<class T, class S, class Method>
+  static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {
+    SendParam send_params;
+    Message* reply = GenerateReply(msg);
+    bool error;
+    if (ReadSendParam(msg, &send_params)) {
+      typename TupleTypes<ReplyParam>::ValueTuple reply_params;
+      DispatchToMethod(obj, func, send_params, &reply_params);
+      WriteParam(reply, reply_params);
+      error = false;
+      LogReplyParamsToMessage(reply_params, msg);
+    } else {
+      NOTREACHED() << "Error deserializing message " << msg->type();
+      reply->set_reply_error();
+      error = true;
+    }
+
+    sender->Send(reply);
+    return !error;
+  }
+
+  template<class T, class Method>
+  static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
+    SendParam send_params;
+    Message* reply = GenerateReply(msg);
+    bool error;
+    if (ReadSendParam(msg, &send_params)) {
+      Tuple1<Message&> t = MakeRefTuple(*reply);
+      ConnectMessageAndReply(msg, reply);
+      DispatchToMethod(obj, func, send_params, &t);
+      error = false;
+    } else {
+      NOTREACHED() << "Error deserializing message " << msg->type();
+      reply->set_reply_error();
+      obj->Send(reply);
+      error = true;
+    }
+    return !error;
+  }
+
+  template<typename TA>
+  static void WriteReplyParams(Message* reply, TA a) {
+    ReplyParam p(a);
+    WriteParam(reply, p);
+  }
+
+  template<typename TA, typename TB>
+  static void WriteReplyParams(Message* reply, TA a, TB b) {
+    ReplyParam p(a, b);
+    WriteParam(reply, p);
+  }
+
+  template<typename TA, typename TB, typename TC>
+  static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
+    ReplyParam p(a, b, c);
+    WriteParam(reply, p);
+  }
+
+  template<typename TA, typename TB, typename TC, typename TD>
+  static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
+    ReplyParam p(a, b, c, d);
+    WriteParam(reply, p);
+  }
+
+  template<typename TA, typename TB, typename TC, typename TD, typename TE>
+  static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
+    ReplyParam p(a, b, c, d, e);
+    WriteParam(reply, p);
+  }
+};
+
+//-----------------------------------------------------------------------------
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_MESSAGE_UTILS_H_
diff --git a/ipc/ipc_message_utils_impl.h b/ipc/ipc_message_utils_impl.h
new file mode 100644 (file)
index 0000000..2e571ed
--- /dev/null
@@ -0,0 +1,45 @@
+// 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.
+//
+// This file contains templates forward declared (but not defined) in
+// ipc_message_utils.h so that they are only instantiated in certain files,
+// notably a few IPC unit tests.
+
+#ifndef IPC_IPC_MESSAGE_UTILS_IMPL_H_
+#define IPC_IPC_MESSAGE_UTILS_IMPL_H_
+
+namespace IPC {
+
+template <class ParamType>
+MessageWithTuple<ParamType>::MessageWithTuple(
+    int32 routing_id, uint32 type, const RefParam& p)
+    : Message(routing_id, type, PRIORITY_NORMAL) {
+  WriteParam(this, p);
+}
+
+// We can't migrate the template for Log() to MessageWithTuple, because each
+// subclass needs to have Log() to call Read(), which instantiates the above
+// template.
+
+template <class SendParamType, class ReplyParamType>
+MessageWithReply<SendParamType, ReplyParamType>::MessageWithReply(
+    int32 routing_id, uint32 type,
+    const RefSendParam& send,
+    const ReplyParam& reply)
+    : SyncMessage(routing_id, type, PRIORITY_NORMAL,
+                  new ParamDeserializer<ReplyParam>(reply)) 
+{
+  WriteParam(this, send);
+}
+
+template <class SendParamType, class ReplyParamType>
+bool MessageWithReply<SendParamType, ReplyParamType>::ReadReplyParam(
+    const Message* msg, typename TupleTypes<ReplyParam>::ValueTuple* p) {
+  void* iter = SyncMessage::GetDataIterator(msg);
+  return ReadParam(msg, &iter, p);
+}
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_MESSAGE_UTILS_IMPL_H_
diff --git a/ipc/ipc_param_traits.h b/ipc/ipc_param_traits.h
new file mode 100644 (file)
index 0000000..e90be18
--- /dev/null
@@ -0,0 +1,24 @@
+// 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 IPC_IPC_PARAM_TRAITS_H_
+#define IPC_IPC_PARAM_TRAITS_H_
+#pragma once
+
+// Our IPC system uses the following partially specialized header to define how
+// a data type is read, written and logged in the IPC system.
+
+namespace IPC {
+
+template <class P> struct ParamTraits {
+};
+
+template <class P>
+struct SimilarTypeTraits {
+  typedef P Type;
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_PARAM_TRAITS_H_
diff --git a/ipc/ipc_platform_file.cc b/ipc/ipc_platform_file.cc
new file mode 100644 (file)
index 0000000..2b15ceb
--- /dev/null
@@ -0,0 +1,43 @@
+// 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 "ipc/ipc_platform_file.h"
+
+namespace IPC {
+
+PlatformFileForTransit GetFileHandleForProcess(base::PlatformFile handle,
+                                               base::ProcessHandle process,
+                                               bool close_source_handle) {
+  IPC::PlatformFileForTransit out_handle;
+#if defined(OS_WIN)
+  DWORD options = DUPLICATE_SAME_ACCESS;
+  if (close_source_handle)
+    options |= DUPLICATE_CLOSE_SOURCE;
+  if (!::DuplicateHandle(::GetCurrentProcess(),
+                         handle,
+                         process,
+                         &out_handle,
+                         0,
+                         FALSE,
+                         options)) {
+    out_handle = IPC::InvalidPlatformFileForTransit();
+  }
+#elif defined(OS_POSIX)
+  // If asked to close the source, we can simply re-use the source fd instead of
+  // dup()ing and close()ing.
+  // When we're not closing the source, we need to duplicate the handle and take
+  // ownership of that. The reason is that this function is often used to
+  // generate IPC messages, and the handle must remain valid until it's sent to
+  // the other process from the I/O thread. Without the dup, calling code might
+  // close the source handle before the message is sent, creating a race
+  // condition.
+  int fd = close_source_handle ? handle : ::dup(handle);
+  out_handle = base::FileDescriptor(fd, true);
+#else
+  #error Not implemented.
+#endif
+  return out_handle;
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_platform_file.h b/ipc/ipc_platform_file.h
new file mode 100644 (file)
index 0000000..daaf21c
--- /dev/null
@@ -0,0 +1,51 @@
+// 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 IPC_IPC_PLATFORM_FILE_H_
+#define IPC_IPC_PLATFORM_FILE_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/platform_file.h"
+#include "base/process.h"
+#include "ipc/ipc_export.h"
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#endif
+
+namespace IPC {
+
+#if defined(OS_WIN)
+typedef base::PlatformFile PlatformFileForTransit;
+#elif defined(OS_POSIX)
+typedef base::FileDescriptor PlatformFileForTransit;
+#endif
+
+inline PlatformFileForTransit InvalidPlatformFileForTransit() {
+#if defined(OS_WIN)
+  return base::kInvalidPlatformFileValue;
+#elif defined(OS_POSIX)
+  return base::FileDescriptor();
+#endif
+}
+
+inline base::PlatformFile PlatformFileForTransitToPlatformFile(
+    const PlatformFileForTransit& transit) {
+#if defined(OS_WIN)
+  return transit;
+#elif defined(OS_POSIX)
+  return transit.fd;
+#endif
+}
+
+// Returns a file handle equivalent to |file| that can be used in |process|.
+IPC_EXPORT PlatformFileForTransit GetFileHandleForProcess(
+    base::PlatformFile file,
+    base::ProcessHandle process,
+    bool close_source_handle);
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_PLATFORM_FILE_H_
diff --git a/ipc/ipc_switches.cc b/ipc/ipc_switches.cc
new file mode 100644 (file)
index 0000000..bcb1225
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (c) 2006-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 "ipc/ipc_switches.h"
+
+#include "base/base_switches.h"
+
+namespace switches {
+
+// Can't find the switch you are looking for? try looking in
+// base/base_switches.cc instead.
+
+// The value of this switch tells the child process which
+// IPC channel the browser expects to use to communicate with it.
+const char kProcessChannelID[]              = "channel";
+
+// Will add kDebugOnStart to every child processes. If a value is passed, it
+// will be used as a filter to determine if the child process should have the
+// kDebugOnStart flag passed on or not.
+const char kDebugChildren[]                 = "debug-children";
+
+}  // namespace switches
+
diff --git a/ipc/ipc_switches.h b/ipc/ipc_switches.h
new file mode 100644 (file)
index 0000000..7c7a833
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+// Defines all the command-line switches used by the IPC infrastructure.
+
+#ifndef IPC_IPC_SWITCHES_H_
+#define IPC_IPC_SWITCHES_H_
+#pragma once
+
+#include "ipc/ipc_export.h"
+
+namespace switches {
+
+IPC_EXPORT extern const char kProcessChannelID[];
+IPC_EXPORT extern const char kDebugChildren[];
+
+}  // namespace switches
+
+#endif  // IPC_IPC_SWITCHES_H_
diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc
new file mode 100644 (file)
index 0000000..c135ef3
--- /dev/null
@@ -0,0 +1,513 @@
+// 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 "ipc/ipc_sync_channel.h"
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/thread_local.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/synchronization/waitable_event_watcher.h"
+#include "ipc/ipc_sync_message.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+using base::WaitableEvent;
+
+namespace IPC {
+// When we're blocked in a Send(), we need to process incoming synchronous
+// messages right away because it could be blocking our reply (either
+// directly from the same object we're calling, or indirectly through one or
+// more other channels).  That means that in SyncContext's OnMessageReceived,
+// we need to process sync message right away if we're blocked.  However a
+// simple check isn't sufficient, because the listener thread can be in the
+// process of calling Send.
+// To work around this, when SyncChannel filters a sync message, it sets
+// an event that the listener thread waits on during its Send() call.  This
+// allows us to dispatch incoming sync messages when blocked.  The race
+// condition is handled because if Send is in the process of being called, it
+// will check the event.  In case the listener thread isn't sending a message,
+// we queue a task on the listener thread to dispatch the received messages.
+// The messages are stored in this queue object that's shared among all
+// SyncChannel objects on the same thread (since one object can receive a
+// sync message while another one is blocked).
+
+class SyncChannel::ReceivedSyncMsgQueue :
+    public base::RefCountedThreadSafe<ReceivedSyncMsgQueue> {
+ public:
+  // Returns the ReceivedSyncMsgQueue instance for this thread, creating one
+  // if necessary.  Call RemoveContext on the same thread when done.
+  static ReceivedSyncMsgQueue* AddContext() {
+    // We want one ReceivedSyncMsgQueue per listener thread (i.e. since multiple
+    // SyncChannel objects can block the same thread).
+    ReceivedSyncMsgQueue* rv = lazy_tls_ptr_.Pointer()->Get();
+    if (!rv) {
+      rv = new ReceivedSyncMsgQueue();
+      ReceivedSyncMsgQueue::lazy_tls_ptr_.Pointer()->Set(rv);
+    }
+    rv->listener_count_++;
+    return rv;
+  }
+
+  // Called on IPC thread when a synchronous message or reply arrives.
+  void QueueMessage(const Message& msg, SyncChannel::SyncContext* context) {
+    bool was_task_pending;
+    {
+      base::AutoLock auto_lock(message_lock_);
+
+      was_task_pending = task_pending_;
+      task_pending_ = true;
+
+      // We set the event in case the listener thread is blocked (or is about
+      // to). In case it's not, the PostTask dispatches the messages.
+      message_queue_.push_back(QueuedMessage(new Message(msg), context));
+    }
+
+    dispatch_event_.Signal();
+    if (!was_task_pending) {
+      listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+          this,
+          &ReceivedSyncMsgQueue::DispatchMessagesTask,
+          scoped_refptr<SyncContext>(context)));
+    }
+  }
+
+  void QueueReply(const Message &msg, SyncChannel::SyncContext* context) {
+    received_replies_.push_back(QueuedMessage(new Message(msg), context));
+  }
+
+  // Called on the listener's thread to process any queues synchronous
+  // messages.
+  void DispatchMessagesTask(SyncContext* context) {
+    {
+      base::AutoLock auto_lock(message_lock_);
+      task_pending_ = false;
+    }
+    context->DispatchMessages();
+  }
+
+  void DispatchMessages(SyncContext* dispatching_context) {
+    SyncMessageQueue delayed_queue;
+    while (true) {
+      Message* message;
+      scoped_refptr<SyncChannel::SyncContext> context;
+      {
+        base::AutoLock auto_lock(message_lock_);
+        if (message_queue_.empty()) {
+          message_queue_ = delayed_queue;
+          break;
+        }
+
+        message = message_queue_.front().message;
+        context = message_queue_.front().context;
+        message_queue_.pop_front();
+      }
+      if (context->restrict_dispatch() && context != dispatching_context) {
+        delayed_queue.push_back(QueuedMessage(message, context));
+      } else {
+        context->OnDispatchMessage(*message);
+        delete message;
+      }
+    }
+  }
+
+  // SyncChannel calls this in its destructor.
+  void RemoveContext(SyncContext* context) {
+    base::AutoLock auto_lock(message_lock_);
+
+    SyncMessageQueue::iterator iter = message_queue_.begin();
+    while (iter != message_queue_.end()) {
+      if (iter->context == context) {
+        delete iter->message;
+        iter = message_queue_.erase(iter);
+      } else {
+        iter++;
+      }
+    }
+
+    if (--listener_count_ == 0) {
+      DCHECK(lazy_tls_ptr_.Pointer()->Get());
+      lazy_tls_ptr_.Pointer()->Set(NULL);
+    }
+  }
+
+  WaitableEvent* dispatch_event() { return &dispatch_event_; }
+  base::MessageLoopProxy* listener_message_loop() {
+    return listener_message_loop_;
+  }
+
+  // Holds a pointer to the per-thread ReceivedSyncMsgQueue object.
+  static base::LazyInstance<base::ThreadLocalPointer<ReceivedSyncMsgQueue> >
+      lazy_tls_ptr_;
+
+  // Called on the ipc thread to check if we can unblock any current Send()
+  // calls based on a queued reply.
+  void DispatchReplies() {
+    for (size_t i = 0; i < received_replies_.size(); ++i) {
+      Message* message = received_replies_[i].message;
+      if (received_replies_[i].context->TryToUnblockListener(message)) {
+        delete message;
+        received_replies_.erase(received_replies_.begin() + i);
+        return;
+      }
+    }
+  }
+
+  base::WaitableEventWatcher* top_send_done_watcher() {
+    return top_send_done_watcher_;
+  }
+
+  void set_top_send_done_watcher(base::WaitableEventWatcher* watcher) {
+    top_send_done_watcher_ = watcher;
+  }
+
+ private:
+  friend class base::RefCountedThreadSafe<ReceivedSyncMsgQueue>;
+
+  // See the comment in SyncChannel::SyncChannel for why this event is created
+  // as manual reset.
+  ReceivedSyncMsgQueue() :
+      dispatch_event_(true, false),
+      listener_message_loop_(base::MessageLoopProxy::current()),
+      task_pending_(false),
+      listener_count_(0),
+      top_send_done_watcher_(NULL) {
+  }
+
+  ~ReceivedSyncMsgQueue() {}
+
+  // Holds information about a queued synchronous message or reply.
+  struct QueuedMessage {
+    QueuedMessage(Message* m, SyncContext* c) : message(m), context(c) { }
+    Message* message;
+    scoped_refptr<SyncChannel::SyncContext> context;
+  };
+
+  typedef std::deque<QueuedMessage> SyncMessageQueue;
+  SyncMessageQueue message_queue_;
+
+  std::vector<QueuedMessage> received_replies_;
+
+  // Set when we got a synchronous message that we must respond to as the
+  // sender needs its reply before it can reply to our original synchronous
+  // message.
+  WaitableEvent dispatch_event_;
+  scoped_refptr<base::MessageLoopProxy> listener_message_loop_;
+  base::Lock message_lock_;
+  bool task_pending_;
+  int listener_count_;
+
+  // The current send done event watcher for this thread. Used to maintain
+  // a local global stack of send done watchers to ensure that nested sync
+  // message loops complete correctly.
+  base::WaitableEventWatcher* top_send_done_watcher_;
+};
+
+base::LazyInstance<base::ThreadLocalPointer<SyncChannel::ReceivedSyncMsgQueue> >
+    SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_(base::LINKER_INITIALIZED);
+
+SyncChannel::SyncContext::SyncContext(
+    Channel::Listener* listener,
+    base::MessageLoopProxy* ipc_thread,
+    WaitableEvent* shutdown_event)
+    : ChannelProxy::Context(listener, ipc_thread),
+      received_sync_msgs_(ReceivedSyncMsgQueue::AddContext()),
+      shutdown_event_(shutdown_event),
+      restrict_dispatch_(false) {
+}
+
+SyncChannel::SyncContext::~SyncContext() {
+  while (!deserializers_.empty())
+    Pop();
+}
+
+// Adds information about an outgoing sync message to the context so that
+// we know how to deserialize the reply.  Returns a handle that's set when
+// the reply has arrived.
+void SyncChannel::SyncContext::Push(SyncMessage* sync_msg) {
+  // Create the tracking information for this message. This object is stored
+  // by value since all members are pointers that are cheap to copy. These
+  // pointers are cleaned up in the Pop() function.
+  //
+  // The event is created as manual reset because in between Signal and
+  // OnObjectSignalled, another Send can happen which would stop the watcher
+  // from being called.  The event would get watched later, when the nested
+  // Send completes, so the event will need to remain set.
+  PendingSyncMsg pending(SyncMessage::GetMessageId(*sync_msg),
+                         sync_msg->GetReplyDeserializer(),
+                         new WaitableEvent(true, false));
+  base::AutoLock auto_lock(deserializers_lock_);
+  deserializers_.push_back(pending);
+}
+
+bool SyncChannel::SyncContext::Pop() {
+  bool result;
+  {
+    base::AutoLock auto_lock(deserializers_lock_);
+    PendingSyncMsg msg = deserializers_.back();
+    delete msg.deserializer;
+    delete msg.done_event;
+    msg.done_event = NULL;
+    deserializers_.pop_back();
+    result = msg.send_result;
+  }
+
+  // We got a reply to a synchronous Send() call that's blocking the listener
+  // thread.  However, further down the call stack there could be another
+  // blocking Send() call, whose reply we received after we made this last
+  // Send() call.  So check if we have any queued replies available that
+  // can now unblock the listener thread.
+  ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+      received_sync_msgs_.get(), &ReceivedSyncMsgQueue::DispatchReplies));
+
+  return result;
+}
+
+WaitableEvent* SyncChannel::SyncContext::GetSendDoneEvent() {
+  base::AutoLock auto_lock(deserializers_lock_);
+  return deserializers_.back().done_event;
+}
+
+WaitableEvent* SyncChannel::SyncContext::GetDispatchEvent() {
+  return received_sync_msgs_->dispatch_event();
+}
+
+void SyncChannel::SyncContext::DispatchMessages() {
+  received_sync_msgs_->DispatchMessages(this);
+}
+
+bool SyncChannel::SyncContext::TryToUnblockListener(const Message* msg) {
+  base::AutoLock auto_lock(deserializers_lock_);
+  if (deserializers_.empty() ||
+      !SyncMessage::IsMessageReplyTo(*msg, deserializers_.back().id)) {
+    return false;
+  }
+
+  if (!msg->is_reply_error()) {
+    deserializers_.back().send_result = deserializers_.back().deserializer->
+        SerializeOutputParameters(*msg);
+  }
+  deserializers_.back().done_event->Signal();
+
+  return true;
+}
+
+void SyncChannel::SyncContext::Clear() {
+  CancelPendingSends();
+  received_sync_msgs_->RemoveContext(this);
+  Context::Clear();
+}
+
+bool SyncChannel::SyncContext::OnMessageReceived(const Message& msg) {
+  // Give the filters a chance at processing this message.
+  if (TryFilters(msg))
+    return true;
+
+  if (TryToUnblockListener(&msg))
+    return true;
+
+  if (msg.should_unblock()) {
+    received_sync_msgs_->QueueMessage(msg, this);
+    return true;
+  }
+
+  if (msg.is_reply()) {
+    received_sync_msgs_->QueueReply(msg, this);
+    return true;
+  }
+
+  return Context::OnMessageReceivedNoFilter(msg);
+}
+
+void SyncChannel::SyncContext::OnChannelError() {
+  CancelPendingSends();
+  shutdown_watcher_.StopWatching();
+  Context::OnChannelError();
+}
+
+void SyncChannel::SyncContext::OnChannelOpened() {
+  shutdown_watcher_.StartWatching(shutdown_event_, this);
+  Context::OnChannelOpened();
+}
+
+void SyncChannel::SyncContext::OnChannelClosed() {
+  CancelPendingSends();
+  shutdown_watcher_.StopWatching();
+  Context::OnChannelClosed();
+}
+
+void SyncChannel::SyncContext::OnSendTimeout(int message_id) {
+  base::AutoLock auto_lock(deserializers_lock_);
+  PendingSyncMessageQueue::iterator iter;
+  for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) {
+    if (iter->id == message_id) {
+      iter->done_event->Signal();
+      break;
+    }
+  }
+}
+
+void SyncChannel::SyncContext::CancelPendingSends() {
+  base::AutoLock auto_lock(deserializers_lock_);
+  PendingSyncMessageQueue::iterator iter;
+  for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++)
+    iter->done_event->Signal();
+}
+
+void SyncChannel::SyncContext::OnWaitableEventSignaled(WaitableEvent* event) {
+  if (event == shutdown_event_) {
+    // Process shut down before we can get a reply to a synchronous message.
+    // Cancel pending Send calls, which will end up setting the send done event.
+    CancelPendingSends();
+  } else {
+    // We got the reply, timed out or the process shutdown.
+    DCHECK_EQ(GetSendDoneEvent(), event);
+    MessageLoop::current()->QuitNow();
+  }
+}
+
+
+SyncChannel::SyncChannel(
+    const IPC::ChannelHandle& channel_handle,
+    Channel::Mode mode,
+    Channel::Listener* listener,
+    base::MessageLoopProxy* ipc_message_loop,
+    bool create_pipe_now,
+    WaitableEvent* shutdown_event)
+    : ChannelProxy(
+          channel_handle, mode, ipc_message_loop,
+          new SyncContext(listener, ipc_message_loop, shutdown_event),
+          create_pipe_now),
+      sync_messages_with_no_timeout_allowed_(true) {
+  // Ideally we only want to watch this object when running a nested message
+  // loop.  However, we don't know when it exits if there's another nested
+  // message loop running under it or not, so we wouldn't know whether to
+  // stop or keep watching.  So we always watch it, and create the event as
+  // manual reset since the object watcher might otherwise reset the event
+  // when we're doing a WaitMany.
+  dispatch_watcher_.StartWatching(sync_context()->GetDispatchEvent(), this);
+}
+
+SyncChannel::~SyncChannel() {
+}
+
+void SyncChannel::SetRestrictDispatchToSameChannel(bool value) {
+  sync_context()->set_restrict_dispatch(value);
+}
+
+bool SyncChannel::Send(Message* message) {
+  return SendWithTimeout(message, base::kNoTimeout);
+}
+
+bool SyncChannel::SendWithTimeout(Message* message, int timeout_ms) {
+  if (!message->is_sync()) {
+    ChannelProxy::Send(message);
+    return true;
+  }
+
+  // *this* might get deleted in WaitForReply.
+  scoped_refptr<SyncContext> context(sync_context());
+  if (context->shutdown_event()->IsSignaled()) {
+    delete message;
+    return false;
+  }
+
+  DCHECK(sync_messages_with_no_timeout_allowed_ ||
+         timeout_ms != base::kNoTimeout);
+  SyncMessage* sync_msg = static_cast<SyncMessage*>(message);
+  context->Push(sync_msg);
+  int message_id = SyncMessage::GetMessageId(*sync_msg);
+  WaitableEvent* pump_messages_event = sync_msg->pump_messages_event();
+
+  ChannelProxy::Send(message);
+
+  if (timeout_ms != base::kNoTimeout) {
+    // We use the sync message id so that when a message times out, we don't
+    // confuse it with another send that is either above/below this Send in
+    // the call stack.
+    context->ipc_message_loop()->PostDelayedTask(FROM_HERE,
+        NewRunnableMethod(context.get(),
+            &SyncContext::OnSendTimeout, message_id), timeout_ms);
+  }
+
+  // Wait for reply, or for any other incoming synchronous messages.
+  // *this* might get deleted, so only call static functions at this point.
+  WaitForReply(context, pump_messages_event);
+
+  return context->Pop();
+}
+
+void SyncChannel::WaitForReply(
+    SyncContext* context, WaitableEvent* pump_messages_event) {
+  context->DispatchMessages();
+  while (true) {
+    WaitableEvent* objects[] = {
+      context->GetDispatchEvent(),
+      context->GetSendDoneEvent(),
+      pump_messages_event
+    };
+
+    unsigned count = pump_messages_event ? 3: 2;
+    size_t result = WaitableEvent::WaitMany(objects, count);
+    if (result == 0 /* dispatch event */) {
+      // We're waiting for a reply, but we received a blocking synchronous
+      // call.  We must process it or otherwise a deadlock might occur.
+      context->GetDispatchEvent()->Reset();
+      context->DispatchMessages();
+      continue;
+    }
+
+    if (result == 2 /* pump_messages_event */)
+      WaitForReplyWithNestedMessageLoop(context);  // Run a nested message loop.
+
+    break;
+  }
+}
+
+void SyncChannel::WaitForReplyWithNestedMessageLoop(SyncContext* context) {
+  base::WaitableEventWatcher send_done_watcher;
+
+  ReceivedSyncMsgQueue* sync_msg_queue = context->received_sync_msgs();
+  DCHECK(sync_msg_queue != NULL);
+
+  base::WaitableEventWatcher* old_send_done_event_watcher =
+      sync_msg_queue->top_send_done_watcher();
+
+  base::WaitableEventWatcher::Delegate* old_delegate = NULL;
+  base::WaitableEvent* old_event = NULL;
+
+  // Maintain a local global stack of send done delegates to ensure that
+  // nested sync calls complete in the correct sequence, i.e. the
+  // outermost call completes first, etc.
+  if (old_send_done_event_watcher) {
+    old_delegate = old_send_done_event_watcher->delegate();
+    old_event = old_send_done_event_watcher->GetWatchedEvent();
+    old_send_done_event_watcher->StopWatching();
+  }
+
+  sync_msg_queue->set_top_send_done_watcher(&send_done_watcher);
+
+  send_done_watcher.StartWatching(context->GetSendDoneEvent(), context);
+  bool old_state = MessageLoop::current()->NestableTasksAllowed();
+
+  MessageLoop::current()->SetNestableTasksAllowed(true);
+  MessageLoop::current()->Run();
+  MessageLoop::current()->SetNestableTasksAllowed(old_state);
+
+  sync_msg_queue->set_top_send_done_watcher(old_send_done_event_watcher);
+  if (old_send_done_event_watcher && old_event) {
+    old_send_done_event_watcher->StartWatching(old_event, old_delegate);
+  }
+}
+
+void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) {
+  DCHECK(event == sync_context()->GetDispatchEvent());
+  // The call to DispatchMessages might delete this object, so reregister
+  // the object watcher first.
+  event->Reset();
+  dispatch_watcher_.StartWatching(event, this);
+  sync_context()->DispatchMessages();
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_sync_channel.h b/ipc/ipc_sync_channel.h
new file mode 100644 (file)
index 0000000..29844da
--- /dev/null
@@ -0,0 +1,200 @@
+// 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 IPC_IPC_SYNC_SENDER_H__
+#define IPC_IPC_SYNC_SENDER_H__
+#pragma once
+
+#include <string>
+#include <deque>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event_watcher.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_sync_message.h"
+
+namespace base {
+class WaitableEvent;
+};
+
+namespace IPC {
+
+class SyncMessage;
+class MessageReplyDeserializer;
+
+// This is similar to ChannelProxy, with the added feature of supporting sending
+// synchronous messages.
+//
+// Overview of how the sync channel works
+// --------------------------------------
+// When the sending thread sends a synchronous message, we create a bunch
+// of tracking info (created in SendWithTimeout, stored in the PendingSyncMsg
+// structure) associated with the message that we identify by the unique
+// "MessageId" on the SyncMessage. Among the things we save is the
+// "Deserializer" which is provided by the sync message. This object is in
+// charge of reading the parameters from the reply message and putting them in
+// the output variables provided by its caller.
+//
+// The info gets stashed in a queue since we could have a nested stack of sync
+// messages (each side could send sync messages in response to sync messages,
+// so it works like calling a function). The message is sent to the I/O thread
+// for dispatch and the original thread blocks waiting for the reply.
+//
+// SyncContext maintains the queue in a threadsafe way and listens for replies
+// on the I/O thread. When a reply comes in that matches one of the messages
+// it's looking for (using the unique message ID), it will execute the
+// deserializer stashed from before, and unblock the original thread.
+//
+//
+// Significant complexity results from the fact that messages are still coming
+// in while the original thread is blocked. Normal async messages are queued
+// and dispatched after the blocking call is complete. Sync messages must
+// be dispatched in a reentrant manner to avoid deadlock.
+//
+//
+// Note that care must be taken that the lifetime of the ipc_thread argument
+// is more than this object.  If the message loop goes away while this object
+// is running and it's used to send a message, then it will use the invalid
+// message loop pointer to proxy it to the ipc thread.
+class IPC_EXPORT SyncChannel : public ChannelProxy,
+                               public base::WaitableEventWatcher::Delegate {
+ public:
+  SyncChannel(const IPC::ChannelHandle& channel_handle,
+              Channel::Mode mode,
+              Channel::Listener* listener,
+              base::MessageLoopProxy* ipc_message_loop,
+              bool create_pipe_now,
+              base::WaitableEvent* shutdown_event);
+  virtual ~SyncChannel();
+
+  virtual bool Send(Message* message);
+  virtual bool SendWithTimeout(Message* message, int timeout_ms);
+
+  // Whether we allow sending messages with no time-out.
+  void set_sync_messages_with_no_timeout_allowed(bool value) {
+    sync_messages_with_no_timeout_allowed_ = value;
+  }
+
+  // Sets this channel to only dispatch its incoming unblocking messages when it
+  // is itself blocked on sending a sync message, not when other channels are.
+  //
+  // Normally, any unblocking message coming from any channel can be dispatched
+  // when any (possibly other) channel is blocked on sending a message. This is
+  // needed in some cases to unblock certain loops (e.g. necessary when some
+  // processes share a window hierarchy), but may cause re-entrancy issues in
+  // some cases where such loops are not possible. This flags allows the tagging
+  // of some particular channels to not re-enter in such cases.
+  void SetRestrictDispatchToSameChannel(bool value);
+
+ protected:
+  class ReceivedSyncMsgQueue;
+  friend class ReceivedSyncMsgQueue;
+
+  // SyncContext holds the per object data for SyncChannel, so that SyncChannel
+  // can be deleted while it's being used in a different thread.  See
+  // ChannelProxy::Context for more information.
+  class SyncContext : public Context,
+                      public base::WaitableEventWatcher::Delegate {
+   public:
+    SyncContext(Channel::Listener* listener,
+                base::MessageLoopProxy* ipc_thread,
+                base::WaitableEvent* shutdown_event);
+
+    // Adds information about an outgoing sync message to the context so that
+    // we know how to deserialize the reply.
+    void Push(SyncMessage* sync_msg);
+
+    // Cleanly remove the top deserializer (and throw it away).  Returns the
+    // result of the Send call for that message.
+    bool Pop();
+
+    // Returns an event that's set when the send is complete, timed out or the
+    // process shut down.
+    base::WaitableEvent* GetSendDoneEvent();
+
+    // Returns an event that's set when an incoming message that's not the reply
+    // needs to get dispatched (by calling SyncContext::DispatchMessages).
+    base::WaitableEvent* GetDispatchEvent();
+
+    void DispatchMessages();
+
+    // Checks if the given message is blocking the listener thread because of a
+    // synchronous send.  If it is, the thread is unblocked and true is
+    // returned. Otherwise the function returns false.
+    bool TryToUnblockListener(const Message* msg);
+
+    // Called on the IPC thread when a sync send that runs a nested message loop
+    // times out.
+    void OnSendTimeout(int message_id);
+
+    base::WaitableEvent* shutdown_event() { return shutdown_event_; }
+
+    ReceivedSyncMsgQueue* received_sync_msgs() {
+      return received_sync_msgs_;
+    }
+
+    void set_restrict_dispatch(bool value) { restrict_dispatch_ = value; }
+    bool restrict_dispatch() const { return restrict_dispatch_; }
+
+   private:
+    virtual ~SyncContext();
+    // ChannelProxy methods that we override.
+
+    // Called on the listener thread.
+    virtual void Clear();
+
+    // Called on the IPC thread.
+    virtual bool OnMessageReceived(const Message& msg);
+    virtual void OnChannelError();
+    virtual void OnChannelOpened();
+    virtual void OnChannelClosed();
+
+    // Cancels all pending Send calls.
+    void CancelPendingSends();
+
+    // WaitableEventWatcher::Delegate implementation.
+    virtual void OnWaitableEventSignaled(base::WaitableEvent* arg);
+
+    typedef std::deque<PendingSyncMsg> PendingSyncMessageQueue;
+    PendingSyncMessageQueue deserializers_;
+    base::Lock deserializers_lock_;
+
+    scoped_refptr<ReceivedSyncMsgQueue> received_sync_msgs_;
+
+    base::WaitableEvent* shutdown_event_;
+    base::WaitableEventWatcher shutdown_watcher_;
+    bool restrict_dispatch_;
+  };
+
+ private:
+  // WaitableEventWatcher::Delegate implementation.
+  virtual void OnWaitableEventSignaled(base::WaitableEvent* arg);
+
+  SyncContext* sync_context() {
+    return reinterpret_cast<SyncContext*>(context());
+  }
+
+  // Both these functions wait for a reply, timeout or process shutdown.  The
+  // latter one also runs a nested message loop in the meantime.
+  static void WaitForReply(
+      SyncContext* context, base::WaitableEvent* pump_messages_event);
+
+  // Runs a nested message loop until a reply arrives, times out, or the process
+  // shuts down.
+  static void WaitForReplyWithNestedMessageLoop(SyncContext* context);
+
+  bool sync_messages_with_no_timeout_allowed_;
+
+  // Used to signal events between the IPC and listener threads.
+  base::WaitableEventWatcher dispatch_watcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncChannel);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_SYNC_SENDER_H__
diff --git a/ipc/ipc_sync_message.cc b/ipc/ipc_sync_message.cc
new file mode 100644 (file)
index 0000000..3a36bf3
--- /dev/null
@@ -0,0 +1,130 @@
+// 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 "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+#include <stack>
+
+#include "base/atomic_sequence_num.h"
+//#include "base/logging.h"
+#include "log.h"
+#include "base/synchronization/waitable_event.h"
+#include "ipc/ipc_sync_message.h"
+
+namespace IPC {
+
+#define kSyncMessageHeaderSize 4
+
+static base::AtomicSequenceNumber g_next_id(base::LINKER_INITIALIZED);
+
+    static base::WaitableEvent* dummy_event = NULL; //new base::WaitableEvent(true, true);
+
+SyncMessage::SyncMessage(
+    int32 routing_id,
+    uint32 type,
+    PriorityValue priority,
+    MessageReplyDeserializer* deserializer)
+    : Message(routing_id, type, priority),
+      deserializer_(deserializer),
+      pump_messages_event_(NULL)
+      {
+  set_sync();
+  set_unblock(true);
+
+  
+  // Add synchronous message data before the message payload.
+  SyncHeader header;
+  header.message_id = g_next_id.GetNext();
+  WriteSyncHeader(this, header);
+}
+
+MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() {
+  MessageReplyDeserializer* rv = deserializer_;
+  DCHECK(rv);
+  deserializer_ = NULL;
+  return rv;
+}
+
+void SyncMessage::EnableMessagePumping() {
+  DCHECK(!pump_messages_event_);
+  set_pump_messages_event(dummy_event);
+}
+
+bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) {
+  if (!msg.is_reply())
+    return false;
+
+  return GetMessageId(msg) == request_id;
+}
+
+void* SyncMessage::GetDataIterator(const Message* msg) {
+  void* iter = const_cast<char*>(msg->payload());
+  UpdateIter(&iter, kSyncMessageHeaderSize);
+  return iter;
+}
+
+int SyncMessage::GetMessageId(const Message& msg) {
+  if (!msg.is_sync() && !msg.is_reply())
+    return 0;
+
+  SyncHeader header;
+  if (!ReadSyncHeader(msg, &header))
+    return 0;
+
+  return header.message_id;
+}
+
+Message* SyncMessage::GenerateReply(const Message* msg) {
+  DCHECK(msg->is_sync()) << "is_sync(" << msg->is_sync() <<")"<<std::endl;
+
+  Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID,
+                               msg->priority());
+  reply->set_reply();
+
+  SyncHeader header;
+
+  // use the same message id, but this time reply bit is set
+  header.message_id = GetMessageId(*msg);
+  WriteSyncHeader(reply, header);
+
+  return reply;
+}
+
+bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) {
+  DCHECK(msg.is_sync() || msg.is_reply());
+
+  void* iter = NULL;
+  bool result = msg.ReadInt(&iter, &header->message_id);
+  if (!result) {
+    NOTREACHED();
+    return false;
+  }
+
+  return true;
+}
+
+bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) {
+  DCHECK(msg->is_sync() || msg->is_reply()); 
+  DCHECK(msg->payload_size() == 0);
+  bool result = msg->WriteInt(header.message_id);
+  if (!result) {
+    NOTREACHED();
+    return false;
+  }
+
+  // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
+  DCHECK(kSyncMessageHeaderSize == msg->payload_size());
+
+  return true;
+}
+
+
+bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) {
+  return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg));
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_sync_message.h b/ipc/ipc_sync_message.h
new file mode 100644 (file)
index 0000000..2c6ed8b
--- /dev/null
@@ -0,0 +1,109 @@
+// 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 IPC_IPC_SYNC_MESSAGE_H_
+#define IPC_IPC_SYNC_MESSAGE_H_
+#pragma once
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+#include <string>
+#include "base/basictypes.h"
+#include "ipc/ipc_message.h"
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace IPC {
+
+class MessageReplyDeserializer;
+
+class IPC_EXPORT SyncMessage : public Message {
+ public:
+  SyncMessage(int32 routing_id, uint32 type, PriorityValue priority,
+              MessageReplyDeserializer* deserializer);
+
+  // Call this to get a deserializer for the output parameters.
+  // Note that this can only be called once, and the caller is responsible
+  // for deleting the deserializer when they're done.
+  MessageReplyDeserializer* GetReplyDeserializer();
+
+  // If this message can cause the receiver to block while waiting for user
+  // input (i.e. by calling MessageBox), then the caller needs to pump window
+  // messages and dispatch asynchronous messages while waiting for the reply.
+  // If this event is passed in, then window messages will start being pumped
+  // when it's set.  Note that this behavior will continue even if the event is
+  // later reset.  The event must be valid until after the Send call returns.
+  void set_pump_messages_event(base::WaitableEvent* event) {
+    pump_messages_event_ = event;
+    if (event) {
+      header()->flags |= PUMPING_MSGS_BIT;
+    } else {
+      header()->flags &= ~PUMPING_MSGS_BIT;
+    }
+  }
+
+  // Call this if you always want to pump messages.  You can call this method
+  // or set_pump_messages_event but not both.
+  void EnableMessagePumping();
+
+  base::WaitableEvent* pump_messages_event() const {
+    return pump_messages_event_;
+  }
+
+  // Returns true if the message is a reply to the given request id.
+  static bool IsMessageReplyTo(const Message& msg, int request_id);
+
+  // Given a reply message, returns an iterator to the beginning of the data
+  // (i.e. skips over the synchronous specific data).
+  static void* GetDataIterator(const Message* msg);
+
+  // Given a synchronous message (or its reply), returns its id.
+  static int GetMessageId(const Message& msg);
+
+  // Generates a reply message to the given message.
+  static Message* GenerateReply(const Message* msg);
+
+ private:
+  struct SyncHeader {
+    // unique ID (unique per sender)
+    int message_id;
+  };
+
+  static bool ReadSyncHeader(const Message& msg, SyncHeader* header);
+  static bool WriteSyncHeader(Message* msg, const SyncHeader& header);
+
+  MessageReplyDeserializer* deserializer_;
+  base::WaitableEvent* pump_messages_event_;
+};
+
+// Used to deserialize parameters from a reply to a synchronous message
+class IPC_EXPORT MessageReplyDeserializer {
+ public:
+  virtual ~MessageReplyDeserializer() {}
+  bool SerializeOutputParameters(const Message& msg);
+ private:
+  // Derived classes need to implement this, using the given iterator (which
+  // is skipped past the header for synchronous messages).
+  virtual bool SerializeOutputParameters(const Message& msg, void* iter) = 0;
+};
+
+// When sending a synchronous message, this structure contains an object
+// that knows how to deserialize the response.
+struct PendingSyncMsg {
+  PendingSyncMsg(int id,
+                 MessageReplyDeserializer* d,
+                 base::WaitableEvent* e)
+      : id(id), deserializer(d), done_event(e), send_result(false) { }
+  int id;
+  MessageReplyDeserializer* deserializer;
+  base::WaitableEvent* done_event;
+  bool send_result;
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_SYNC_MESSAGE_H_
diff --git a/ipc/ipc_sync_message_filter.cc b/ipc/ipc_sync_message_filter.cc
new file mode 100644 (file)
index 0000000..cffbaa6
--- /dev/null
@@ -0,0 +1,127 @@
+// 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 "ipc/ipc_sync_message_filter.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "ipc/ipc_sync_message.h"
+
+namespace IPC {
+
+SyncMessageFilter::SyncMessageFilter(base::WaitableEvent* shutdown_event)
+    : channel_(NULL),
+      listener_loop_(MessageLoop::current()),
+      io_loop_(NULL),
+      shutdown_event_(shutdown_event) {
+}
+
+SyncMessageFilter::~SyncMessageFilter() {
+}
+
+bool SyncMessageFilter::Send(Message* message) {
+  {
+    base::AutoLock auto_lock(lock_);
+    if (!io_loop_) {
+      delete message;
+      return false;
+    }
+  }
+
+  if (!message->is_sync()) {
+    io_loop_->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this, &SyncMessageFilter::SendOnIOThread, message));
+    return true;
+  }
+
+  base::WaitableEvent done_event(true, false);
+  PendingSyncMsg pending_message(
+      SyncMessage::GetMessageId(*message),
+      reinterpret_cast<SyncMessage*>(message)->GetReplyDeserializer(),
+      &done_event);
+
+  {
+    base::AutoLock auto_lock(lock_);
+    // Can't use this class on the main thread or else it can lead to deadlocks.
+    // Also by definition, can't use this on IO thread since we're blocking it.
+    DCHECK(MessageLoop::current() != listener_loop_);
+    DCHECK(MessageLoop::current() != io_loop_);
+    pending_sync_messages_.insert(&pending_message);
+  }
+
+  io_loop_->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this, &SyncMessageFilter::SendOnIOThread, message));
+
+  base::WaitableEvent* events[2] = { shutdown_event_, &done_event };
+  base::WaitableEvent::WaitMany(events, 2);
+
+  {
+    base::AutoLock auto_lock(lock_);
+    delete pending_message.deserializer;
+    pending_sync_messages_.erase(&pending_message);
+  }
+
+  return pending_message.send_result;
+}
+
+void SyncMessageFilter::SendOnIOThread(Message* message) {
+  if (channel_) {
+    channel_->Send(message);
+    return;
+  }
+
+  if (message->is_sync()) {
+    // We don't know which thread sent it, but it doesn't matter, just signal
+    // them all.
+    SignalAllEvents();
+  }
+
+  delete message;
+}
+
+void SyncMessageFilter::SignalAllEvents() {
+  base::AutoLock auto_lock(lock_);
+  for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
+       iter != pending_sync_messages_.end(); ++iter) {
+    (*iter)->done_event->Signal();
+  }
+}
+
+void SyncMessageFilter::OnFilterAdded(Channel* channel) {
+  channel_ = channel;
+  base::AutoLock auto_lock(lock_);
+  io_loop_ = MessageLoop::current();
+}
+
+void SyncMessageFilter::OnChannelError() {
+  channel_ = NULL;
+  SignalAllEvents();
+}
+
+void SyncMessageFilter::OnChannelClosing() {
+  channel_ = NULL;
+  SignalAllEvents();
+}
+
+bool SyncMessageFilter::OnMessageReceived(const Message& message) {
+  base::AutoLock auto_lock(lock_);
+  for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
+       iter != pending_sync_messages_.end(); ++iter) {
+    if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) {
+      if (!message.is_reply_error()) {
+        (*iter)->send_result =
+            (*iter)->deserializer->SerializeOutputParameters(message);
+      }
+      (*iter)->done_event->Signal();
+      return true;
+    }
+  }
+
+  return false;
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_sync_message_filter.h b/ipc/ipc_sync_message_filter.h
new file mode 100644 (file)
index 0000000..0dc471a
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 IPC_IPC_SYNC_MESSAGE_FILTER_H_
+#define IPC_IPC_SYNC_MESSAGE_FILTER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_sync_message.h"
+#include <set>
+
+namespace base {
+class WaitableEvent;
+}
+
+class MessageLoop;
+
+namespace IPC {
+
+class MessageReplyDeserializer;
+
+// This MessageFilter allows sending synchronous IPC messages from a thread
+// other than the listener thread associated with the SyncChannel.  It does not
+// support fancy features that SyncChannel does, such as handling recursion or
+// receiving messages while waiting for a response.  Note that this object can
+// be used to send simultaneous synchronous messages from different threads.
+class IPC_EXPORT SyncMessageFilter : public ChannelProxy::MessageFilter,
+                                     public Message::Sender {
+ public:
+  explicit SyncMessageFilter(base::WaitableEvent* shutdown_event);
+  virtual ~SyncMessageFilter();
+
+  // Message::Sender implementation.
+  virtual bool Send(Message* message);
+
+  // ChannelProxy::MessageFilter implementation.
+  virtual void OnFilterAdded(Channel* channel);
+  virtual void OnChannelError();
+  virtual void OnChannelClosing();
+  virtual bool OnMessageReceived(const Message& message);
+
+ private:
+  void SendOnIOThread(Message* message);
+  // Signal all the pending sends as done, used in an error condition.
+  void SignalAllEvents();
+
+  // The channel to which this filter was added.
+  Channel* channel_;
+
+  MessageLoop* listener_loop_;  // The process's main thread.
+  MessageLoop* io_loop_;  // The message loop where the Channel lives.
+
+  typedef std::set<PendingSyncMsg*> PendingSyncMessages;
+  PendingSyncMessages pending_sync_messages_;
+
+  // Locks data members above.
+  base::Lock lock_;
+
+  base::WaitableEvent* shutdown_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncMessageFilter);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_SYNC_MESSAGE_FILTER_H_
diff --git a/ipc/param_traits_log_macros.h b/ipc/param_traits_log_macros.h
new file mode 100644 (file)
index 0000000..8259a0d
--- /dev/null
@@ -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.
+
+#ifndef IPC_PARAM_TRAITS_LOG_MACROS_H_
+#define IPC_PARAM_TRAITS_LOG_MACROS_H_
+#pragma once
+
+#include <string>
+
+// Null out all the macros that need nulling.
+#include "ipc/ipc_message_null_macros.h"
+
+// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
+#undef IPC_STRUCT_BEGIN
+#undef IPC_STRUCT_MEMBER
+#undef IPC_STRUCT_END
+#define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
+#define IPC_STRUCT_MEMBER(type, name) IPC_STRUCT_TRAITS_MEMBER(name)
+#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
+
+// Set up so next include will generate log methods.
+#undef IPC_STRUCT_TRAITS_BEGIN
+#undef IPC_STRUCT_TRAITS_MEMBER
+#undef IPC_STRUCT_TRAITS_PARENT
+#undef IPC_STRUCT_TRAITS_END
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+  void ParamTraits<struct_name>::Log(const param_type& p, std::string* l) { \
+    bool needs_comma = false; \
+    l->append("(");
+#define IPC_STRUCT_TRAITS_MEMBER(name) \
+    if (needs_comma) \
+      l->append(", "); \
+    LogParam(p.name, l); \
+    needs_comma = true;
+#define IPC_STRUCT_TRAITS_PARENT(type) \
+    if (needs_comma) \
+      l->append(", "); \
+      ParamTraits<type>::Log(p, l); \
+      needs_comma = true;
+#define IPC_STRUCT_TRAITS_END() \
+    l->append(")"); \
+  }
+
+#undef IPC_ENUM_TRAITS
+#define IPC_ENUM_TRAITS(enum_name) \
+  void ParamTraits<enum_name>::Log(const param_type& p, std::string* l) { \
+    LogParam(static_cast<int>(p), l); \
+  }
+
+#endif  // IPC_PARAM_TRAITS_LOG_MACROS_H_
+
diff --git a/ipc/param_traits_macros.h b/ipc/param_traits_macros.h
new file mode 100644 (file)
index 0000000..df57adf
--- /dev/null
@@ -0,0 +1,39 @@
+// 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 IPC_PARAM_TRAITS_MACROS_H_
+#define IPC_PARAM_TRAITS_MACROS_H_
+
+#include <string>
+
+// Traits generation for structs.
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+  namespace IPC { \
+    template <> \
+    struct ParamTraits<struct_name> { \
+      typedef struct_name param_type; \
+      static void Write(Message* m, const param_type& p); \
+      static bool Read(const Message* m, void** iter, param_type* p); \
+      static void Log(const param_type& p, std::string* l); \
+    }; \
+  }
+
+#define IPC_STRUCT_TRAITS_MEMBER(name)
+#define IPC_STRUCT_TRAITS_PARENT(type)
+#define IPC_STRUCT_TRAITS_END()
+
+// Traits generation for enums.
+#define IPC_ENUM_TRAITS(enum_name) \
+  namespace IPC { \
+    template <> \
+    struct ParamTraits<enum_name> { \
+      typedef enum_name param_type; \
+      static void Write(Message* m, const param_type& p); \
+      static bool Read(const Message* m, void** iter, param_type* p); \
+      static void Log(const param_type& p, std::string* l); \
+    }; \
+  }
+
+#endif  // IPC_PARAM_TRAITS_MACROS_H_
+
diff --git a/ipc/param_traits_read_macros.h b/ipc/param_traits_read_macros.h
new file mode 100644 (file)
index 0000000..f0b88bc
--- /dev/null
@@ -0,0 +1,45 @@
+// 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 IPC_PARAM_TRAITS_READ_MACROS_H_
+#define IPC_PARAM_TRAITS_READ_MACROS_H_
+#pragma once
+
+// Null out all the macros that need nulling.
+#include "ipc/ipc_message_null_macros.h"
+
+// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
+#undef IPC_STRUCT_BEGIN
+#undef IPC_STRUCT_MEMBER
+#undef IPC_STRUCT_END
+#define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
+#define IPC_STRUCT_MEMBER(type, name) IPC_STRUCT_TRAITS_MEMBER(name)
+#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
+
+// Set up so next include will generate read methods.
+#undef IPC_STRUCT_TRAITS_BEGIN
+#undef IPC_STRUCT_TRAITS_MEMBER
+#undef IPC_STRUCT_TRAITS_PARENT
+#undef IPC_STRUCT_TRAITS_END
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+  bool ParamTraits<struct_name>:: \
+      Read(const Message* m, void** iter, param_type* p) { \
+    return
+#define IPC_STRUCT_TRAITS_MEMBER(name) ReadParam(m, iter, &p->name) &&
+#define IPC_STRUCT_TRAITS_PARENT(type) ParamTraits<type>::Read(m, iter, p) &&
+#define IPC_STRUCT_TRAITS_END() 1; }
+
+#undef IPC_ENUM_TRAITS
+#define IPC_ENUM_TRAITS(enum_name) \
+  bool ParamTraits<enum_name>:: \
+      Read(const Message* m, void** iter, param_type* p) { \
+    int type; \
+    if (!m->ReadInt(iter, &type)) \
+      return false; \
+    *p = static_cast<param_type>(type); \
+    return true; \
+  }
+
+#endif  // IPC_PARAM_TRAITS_READ_MACROS_H_
+
diff --git a/ipc/param_traits_write_macros.h b/ipc/param_traits_write_macros.h
new file mode 100644 (file)
index 0000000..844c385
--- /dev/null
@@ -0,0 +1,38 @@
+// 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 IPC_PARAM_TRAITS_WRITE_MACROS_H_
+#define IPC_PARAM_TRAITS_WRITE_MACROS_H_
+#pragma once
+
+// Null out all the macros that need nulling.
+#include "ipc/ipc_message_null_macros.h"
+
+// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
+#undef IPC_STRUCT_BEGIN
+#undef IPC_STRUCT_MEMBER
+#undef IPC_STRUCT_END
+#define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
+#define IPC_STRUCT_MEMBER(type, name) IPC_STRUCT_TRAITS_MEMBER(name)
+#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
+
+// Set up so next include will generate write methods.
+#undef IPC_STRUCT_TRAITS_BEGIN
+#undef IPC_STRUCT_TRAITS_MEMBER
+#undef IPC_STRUCT_TRAITS_PARENT
+#undef IPC_STRUCT_TRAITS_END
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+  void ParamTraits<struct_name>::Write(Message* m, const param_type& p) {
+#define IPC_STRUCT_TRAITS_MEMBER(name) WriteParam(m, p.name);
+#define IPC_STRUCT_TRAITS_PARENT(type) ParamTraits<type>::Write(m, p);
+#define IPC_STRUCT_TRAITS_END() }
+
+#undef IPC_ENUM_TRAITS
+#define IPC_ENUM_TRAITS(enum_name) \
+  void ParamTraits<enum_name>::Write(Message* m, const param_type& p) { \
+    m->WriteInt(static_cast<int>(p)); \
+  }
+
+#endif  // IPC_PARAM_TRAITS_WRITE_MACROS_H_
+
diff --git a/ipc/struct_constructor_macros.h b/ipc/struct_constructor_macros.h
new file mode 100644 (file)
index 0000000..67bfcfb
--- /dev/null
@@ -0,0 +1,20 @@
+// 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 IPC_STRUCT_CONSTRUCTOR_MACROS_H_
+#define IPC_STRUCT_CONSTRUCTOR_MACROS_H_
+
+// Null out all the macros that need nulling.
+#include "ipc/ipc_message_null_macros.h"
+
+// Set up so next include will generate constructors.
+#undef IPC_STRUCT_BEGIN
+#undef IPC_STRUCT_MEMBER
+#undef IPC_STRUCT_END
+#define IPC_STRUCT_BEGIN(struct_name) struct_name::struct_name() : NoParams()
+#define IPC_STRUCT_MEMBER(type, name) , name()
+#define IPC_STRUCT_END() {}
+
+#endif  // IPC_STRUCT_CONSTRUCTOR_MACROS_H_
+
diff --git a/ipc/struct_destructor_macros.h b/ipc/struct_destructor_macros.h
new file mode 100644 (file)
index 0000000..bf3dc95
--- /dev/null
@@ -0,0 +1,16 @@
+// 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 IPC_STRUCT_DESTRUCTOR_MACROS_H_
+#define IPC_STRUCT_DESTRUCTOR_MACROS_H_
+
+// Null out all the macros that need nulling.
+#include "ipc/ipc_message_null_macros.h"
+
+// Set up so next include will generate destructors.
+#undef IPC_STRUCT_BEGIN
+#define IPC_STRUCT_BEGIN(struct_name) struct_name::~struct_name() {}
+
+#endif  // IPC_STRUCT_DESTRUCTOR_MACROS_H_
+
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
new file mode 100644 (file)
index 0000000..1a4ae13
--- /dev/null
@@ -0,0 +1,250 @@
+// 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/sync_socket.h"
+
+#include <stdio.h>
+#include <string>
+#include <sstream>
+
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "build/build_config.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_message_utils_impl.h"
+#include "ipc/ipc_tests.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#endif
+
+enum IPCMessageIds {
+  UNUSED_IPC_TYPE,
+  SERVER_FIRST_IPC_TYPE,    // SetHandle message sent to server.
+  SERVER_SECOND_IPC_TYPE,   // Shutdown message sent to server.
+  CLIENT_FIRST_IPC_TYPE     // Response message sent to client.
+};
+
+namespace {
+const char kHelloString[] = "Hello, SyncSocket Client";
+const size_t kHelloStringLength = arraysize(kHelloString);
+}  // namespace
+
+// Message class to pass a base::SyncSocket::Handle to another process.
+// This is not as easy as it sounds, because of the differences in transferring
+// Windows HANDLEs versus posix file descriptors.
+#if defined(OS_WIN)
+class MsgClassSetHandle
+    : public IPC::MessageWithTuple< Tuple1<base::SyncSocket::Handle> > {
+ public:
+  enum { ID = SERVER_FIRST_IPC_TYPE };
+  explicit MsgClassSetHandle(const base::SyncSocket::Handle arg1)
+      : IPC::MessageWithTuple< Tuple1<base::SyncSocket::Handle> >(
+            MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MsgClassSetHandle);
+};
+#elif defined(OS_POSIX)
+class MsgClassSetHandle
+    : public IPC::MessageWithTuple< Tuple1<base::FileDescriptor> > {
+ public:
+  enum { ID = SERVER_FIRST_IPC_TYPE };
+  explicit MsgClassSetHandle(const base::FileDescriptor& arg1)
+      : IPC::MessageWithTuple< Tuple1<base::FileDescriptor> >(
+            MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MsgClassSetHandle);
+};
+#else
+# error "What platform?"
+#endif  // defined(OS_WIN)
+
+// Message class to pass a response to the server.
+class MsgClassResponse
+    : public IPC::MessageWithTuple< Tuple1<std::string> > {
+ public:
+  enum { ID = CLIENT_FIRST_IPC_TYPE };
+  explicit MsgClassResponse(const std::string& arg1)
+      : IPC::MessageWithTuple< Tuple1<std::string> >(
+            MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MsgClassResponse);
+};
+
+// Message class to tell the server to shut down.
+class MsgClassShutdown
+    : public IPC::MessageWithTuple< Tuple0 > {
+ public:
+  enum { ID = SERVER_SECOND_IPC_TYPE };
+  MsgClassShutdown()
+      : IPC::MessageWithTuple< Tuple0 >(
+            MSG_ROUTING_CONTROL, ID, MakeTuple()) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MsgClassShutdown);
+};
+
+// The SyncSocket server listener class processes two sorts of
+// messages from the client.
+class SyncSocketServerListener : public IPC::Channel::Listener {
+ public:
+     SyncSocketServerListener() : chan_(NULL) {
+  }
+
+  void Init(IPC::Channel* chan) {
+    chan_ = chan;
+  }
+
+  virtual bool OnMessageReceived(const IPC::Message& msg) {
+    if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+      IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
+        IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
+        IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
+      IPC_END_MESSAGE_MAP()
+    }
+    return true;
+  }
+
+ private:
+  // This sort of message is sent first, causing the transfer of
+  // the handle for the SyncSocket.  This message sends a buffer
+  // on the SyncSocket and then sends a response to the client.
+#if defined(OS_WIN)
+  void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
+    SetHandle(handle);
+  }
+#elif defined(OS_POSIX)
+  void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
+    SetHandle(fd_struct.fd);
+  }
+#else
+# error "What platform?"
+#endif  // defined(OS_WIN)
+
+  void SetHandle(base::SyncSocket::Handle handle) {
+    base::SyncSocket sync_socket(handle);
+    EXPECT_EQ(sync_socket.Send(static_cast<const void*>(kHelloString),
+                               kHelloStringLength), kHelloStringLength);
+    IPC::Message* msg = new MsgClassResponse(kHelloString);
+    EXPECT_TRUE(chan_->Send(msg));
+  }
+
+  // When the client responds, it sends back a shutdown message,
+  // which causes the message loop to exit.
+  void OnMsgClassShutdown() {
+    MessageLoop::current()->Quit();
+  }
+
+  IPC::Channel* chan_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
+};
+
+// Runs the fuzzing server child mode. Returns when the preset number
+// of messages have been received.
+MULTIPROCESS_TEST_MAIN(RunSyncSocketServer) {
+  MessageLoopForIO main_message_loop;
+  SyncSocketServerListener listener;
+  IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_CLIENT, &listener);
+  EXPECT_TRUE(chan.Connect());
+  listener.Init(&chan);
+  MessageLoop::current()->Run();
+  return 0;
+}
+
+// The SyncSocket client listener only processes one sort of message,
+// a response from the server.
+class SyncSocketClientListener : public IPC::Channel::Listener {
+ public:
+  SyncSocketClientListener() {
+  }
+
+  void Init(base::SyncSocket* socket, IPC::Channel* chan) {
+    socket_ = socket;
+    chan_ = chan;
+  }
+
+  virtual bool OnMessageReceived(const IPC::Message& msg) {
+    if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+      IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
+        IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
+      IPC_END_MESSAGE_MAP()
+    }
+    return true;
+  }
+
+ private:
+  // When a response is received from the server, it sends the same
+  // string as was written on the SyncSocket.  These are compared
+  // and a shutdown message is sent back to the server.
+  void OnMsgClassResponse(const std::string& str) {
+    // We rely on the order of sync_socket.Send() and chan_->Send() in
+    // the SyncSocketServerListener object.
+    EXPECT_EQ(kHelloStringLength, socket_->Peek());
+    char buf[kHelloStringLength];
+    socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
+    EXPECT_EQ(strcmp(str.c_str(), buf), 0);
+    // After receiving from the socket there should be no bytes left.
+    EXPECT_EQ(0U, socket_->Peek());
+    IPC::Message* msg = new MsgClassShutdown();
+    EXPECT_TRUE(chan_->Send(msg));
+    MessageLoop::current()->Quit();
+  }
+
+  base::SyncSocket* socket_;
+  IPC::Channel* chan_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
+};
+
+class SyncSocketTest : public IPCChannelTest {
+};
+
+TEST_F(SyncSocketTest, SanityTest) {
+  SyncSocketClientListener listener;
+  IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_SERVER,
+                    &listener);
+  base::ProcessHandle server_process = SpawnChild(SYNC_SOCKET_SERVER, &chan);
+  ASSERT_TRUE(server_process);
+  // Create a pair of SyncSockets.
+  base::SyncSocket* pair[2];
+  base::SyncSocket::CreatePair(pair);
+  // Immediately after creation there should be no pending bytes.
+  EXPECT_EQ(0U, pair[0]->Peek());
+  EXPECT_EQ(0U, pair[1]->Peek());
+  base::SyncSocket::Handle target_handle;
+  // Connect the channel and listener.
+  ASSERT_TRUE(chan.Connect());
+  listener.Init(pair[0], &chan);
+#if defined(OS_WIN)
+  // On windows we need to duplicate the handle into the server process.
+  BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1]->handle(),
+                                server_process, &target_handle,
+                                0, FALSE, DUPLICATE_SAME_ACCESS);
+  EXPECT_TRUE(retval);
+  // Set up a message to pass the handle to the server.
+  IPC::Message* msg = new MsgClassSetHandle(target_handle);
+#else
+  target_handle = pair[1]->handle();
+  // Set up a message to pass the handle to the server.
+  base::FileDescriptor filedesc(target_handle, false);
+  IPC::Message* msg = new MsgClassSetHandle(filedesc);
+#endif  // defined(OS_WIN)
+  EXPECT_TRUE(chan.Send(msg));
+  // Use the current thread as the I/O thread.
+  MessageLoop::current()->Run();
+  // Shut down.
+  delete pair[0];
+  delete pair[1];
+  EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
+  base::CloseProcessHandle(server_process);
+}
diff --git a/log.h b/log.h
new file mode 100644 (file)
index 0000000..90f87eb
--- /dev/null
+++ b/log.h
@@ -0,0 +1,26 @@
+// 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_LOGGING_H_
+#define BASE_LOGGING_H_
+#pragma once
+
+//namespace logging {
+#define DCHECK(x)    if (!(x)) std::cout << "Check failed"
+#define CHECK(x)     if (!(x)) std::cout << "Check failed"
+#define NOTREACHED()      std::cout << "Not reached"                                                                                       
+#define DCHECK_EQ(x, y)   if ((x) != (y)) std::cout << "Check failed"
+#define DCHECK_LE(x, y)   if ((x) > (y)) std::cout << "Check failed" 
+#define DCHECK_GE(x, y)   if ((x) < (y)) std::cout << "Check failed" 
+#define DCHECK_NE(x, y)   if ((x) == (y)) std::cout << "Check failed"
+#define CHECK_NE(x, y)   if ((x) == (y)) std::cout << "Check failed"
+//#define MAX(x,y)        ((x) > (y) ? (x) : (y))                                                                
+
+#ifndef WARN_UNUSED_RESULT                                                                                                              
+//#define WARN_UNUSED_RESULT
+#endif
+
+//}  // namespace base
+
+#endif  // BASE_LOGGING_H_
diff --git a/packaging/chromium.changes b/packaging/chromium.changes
new file mode 100644 (file)
index 0000000..771dbc8
--- /dev/null
@@ -0,0 +1,2 @@
+* Fri Jan 18 2013 Anas Nashif <anas.nashif@intel.com> submit/trunk/20121227.051414@062f276
+- Support installation in lib64
diff --git a/packaging/chromium.spec b/packaging/chromium.spec
new file mode 100755 (executable)
index 0000000..cb64040
--- /dev/null
@@ -0,0 +1,55 @@
+Name:       chromium
+Summary:    chromium library
+Version:    1.0
+Release:    1
+VCS:        external/chromium#submit/master/20130204.054301-1-gf46f96e2520bef5f41566b1752fa700ecbb2e164
+Group:      TO_BE/FILLED_IN
+License:    BSD
+Source0:    %{name}-%{version}.tar.gz
+BuildRequires:  cmake
+
+%description
+chromium library
+
+%package devel
+Summary:    chromium library (devel)
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+chromium library (devel)
+
+%prep
+%setup -q
+
+%build
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+%ifarch %{ix86}
+CXXFLAGS="$CXXFLAGS -D_OSP_DEBUG_ -D_OSP_X86_ -D_OSP_EMUL_" %cmake .  -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+%else
+CXXFLAGS="$CXXFLAGS -D_OSP_DEBUG_ -D_OSP_ARMEL_" %cmake .  -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+%endif
+# Call make instruction with smp support
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp %{_builddir}/%{name}-%{version}/LICENSE  %{buildroot}/usr/share/license/%{name}
+
+%make_install
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%manifest chromium.manifest
+%defattr(-,root,root,-)
+/usr/share/license/%{name}
+%{_libdir}/libchromium.so*
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/chromium/*
+%{_libdir}/pkgconfig/chromium.pc