Initial import of Cobalt 2.8885 2016-07-27
diff --git a/src/.clang-format b/src/.clang-format
new file mode 100644
index 0000000..d5c7b08
--- /dev/null
+++ b/src/.clang-format
@@ -0,0 +1,3 @@
+# Defines the Chromium style for automatic reformatting.

+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html

+BasedOnStyle: Chromium

diff --git a/src/AUTHORS b/src/AUTHORS
new file mode 100644
index 0000000..5a7ed82
--- /dev/null
+++ b/src/AUTHORS
@@ -0,0 +1,12 @@
+# Names should be added to this file with this pattern:
+#
+# For individuals:
+#   Name <email address>
+#
+# For organizations:
+#   Organization <fnmatch pattern>
+#
+# See python fnmatch module documentation for more information.
+
+The Chromium Authors <*@chromium.org>
+Google Inc. <*@google.com>
diff --git a/src/LICENSE b/src/LICENSE
new file mode 100644
index 0000000..3d0f7d3
--- /dev/null
+++ b/src/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2013 The Chromium Authors. 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.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * 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.
diff --git a/src/README.cobalt.txt b/src/README.cobalt.txt
new file mode 100644
index 0000000..bc2d9c7
--- /dev/null
+++ b/src/README.cobalt.txt
@@ -0,0 +1,2 @@
+This is a fork of the chromium repository at http://git.chromium.org/git/chromium.git
+
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 0000000..2d2efba
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,247 @@
+# Cobalt
+
+## Overview
+
+Cobalt is a lightweight application container (i.e. an application runtime, like
+a JVM or the Flash Player) that is compatible with a subset of the W3C HTML5
+specifications. If you author a single-page web application (SPA) that complies
+with the Cobalt Subset of W3C standards, it will run as well as possible on all
+the devices that Cobalt supports.
+
+
+## Motivation
+
+The Cobalt Authors originally maintained a port of Chromium called H5VCC, the
+HTML5 Video Container for Consoles, ported to each of the major game consoles,
+designed to run our HTML5-based video browse and play application. This took a
+long time to port to each platform, consisted of 9 million lines of C++ code
+(before we touched it), was dangerous to modify without unintended consequences,
+and was thoroughly designed for a resource-rich, multi-process environment
+(e.g. a desktop, laptop, or modern smartphone).
+
+After wrestling with this for several years, we imagined an environment that was
+not designed for traditional scrolling web content, but was intended to be a
+runtime environment for rich client applications built with the same
+technologies -- HTML, CSS, JavaScript -- and designed from the ground-up to run
+on constrained, embedded, Living Room Consumer Electronics (CE) devices, such as
+Game Consoles, Set-Top Boxes (e.g. Cable, Satellite), OTT devices (e.g. Roku,
+Apple TV, Chromecast, Fire TV), Blu-ray Disc Players, and Smart TVs.
+
+These constraints (not intended to be a canonical list) make this device
+spectrum vastly different from the desktop computer environment targeted by
+Chromium, FireFox, and IE:
+
+  * **Limited Memory.** All except the very latest, expensive CE devices have a
+    very small amount of memory available for applications. This usually is
+    somewhere in the ballpark of 200MB-500MB, including graphics and media
+    memory, as opposed to multiple gigabytes of CPU memory (and more gigabytes
+    of GPU memory) in modern desktop and laptop computers, and mobile devices.
+  * **Slow CPUs.** Most CE devices have much slower CPUs than what is available
+    on even a budget desktop computer. Minor performance concerns can be greatly
+    exaggerated, which seriously affects priorities.
+  * **Fewer cores.** CE System-on-a-Chip (SoC) processors often do not have as
+    many processor cores as we are used to in modern computers. Many deployed
+    devices still only have a single core.
+  * **Sometimes No GPU.** Not all CE devices have a monster GPU to throw shaders
+    at to offload CPU work. A different strategy is required to maximize
+    leverage of an accelerated blitter, which is all some older devices
+    have. Some newer CE devices have a GPU, but it's not nearly as powerful as
+    what one would even see on a laptop.
+  * **Sometimes No JIT.** Many CE devices are dealing with "High-Value Content,"
+    and, as such, are very sensitive to security concerns. Ensuring that
+    writable pages are not executable is a strong security protocol that can
+    prevent a wide spectrum of attacks. But, as a side effect, this also means
+    no ability to JIT.
+  * **Heterogenous Development Environments.** This is slowly evening out, but
+    all CE devices run on custom hardware, often with proprietary methods of
+    building, packaging, deploying, and running programs. Almost all CE devices
+    have ARM or MIPS processors instead of the more familiar x86. Sometimes the
+    toolchain doesn't support contemporary C++11 features. Sometimes the OS
+    isn't POSIX, or it tries to be, but it is only partially implemented.
+    Sometimes the program entry point is in another language or architecture
+    that requires a "trampoline" over to native binary code.
+  * **No navigation.** The point of a Single-Page Application is that you don't
+    go through the HTTP page dance every time you switch screens. It's slow, and
+    provides poor user feedback, not to mention a jarring transition. Instead,
+    one loads data from an XMLHttpRequest (XHR), and then updates one's DOM to
+    reflect the new data. AJAX! Web 2.0!!
+  * **No scrolling.** Well, full-screen, 10-foot UI SPA apps might scroll, but
+    not like traditional web pages, with scroll bars and a mouse
+    wheel. Scrolling is generally built into the app very carefully, with
+    support for a Directional Pad and a focus cursor.
+
+
+## Architecture
+
+The Cobalt Authors forked H5VCC, removed most of the Chromium code -- in
+particular WebCore and the Chrome Renderer and Compositor -- and built up from
+scratch an implementation of a simplified subset of HTML, the CSS Box Model for
+layout, and the Web APIs that were really needed to build a full-screen SPA
+browse and play application.
+
+The Cobalt technology stack has these major components, roughly in a high-level
+application to a low-level platform order:
+
+  * **Web Implementation** - This is where the W3C standards are implemented,
+    ultimately producing an annotated DOM tree that can be passed into the
+    Layout Engine to produce a Render Tree.
+  * **JavaScript Engine** - We have, perhaps surprisingly, *not* written our own
+    JavaScript Engine from scratch. Because of the JITing constraint, we have to
+    be flexible with which engine(s) we work with. We have a bindings layer that
+    interfaces with the JS Engine so that application script can interface with
+    natively-backed objects (like DOM elements).
+  * **Layout Engine** - The Layout Engine takes an annotated DOM Document
+    produced by the Web Implementation and JavaScript Engine working together,
+    and calculates a tree of rendering commands to send to the renderer (i.e. a
+    Render Tree). It caches intermediate layout artifacts so that subsequent
+    incremental layouts can be sped up.
+  * **Renderer/Skia** - The Renderer walks a Render Tree produced by the Layout
+    Engine, rasterizes it using the third-party graphics library Skia, and swaps
+    it to the front buffer. There are two major paths here, one using Hardware
+    Skia on OpenGL ES 2.0, and one using Software Skia combined with the
+    hardware-accelerated Starboard Blitter. Note that the renderer runs in a
+    different thread from the Layout Engine, and can interpolate animations that
+    do not require re-layout. This decouples rendering from Layout and
+    JavaScript, allowing for smooth, consistent animations on platforms with a
+    variety of capabilities.
+  * **Net / Media** - These are Chromium's Network and Media engines. We are
+    using them directly, as they don't cause any particular problems with the
+    extra constraints listed above.
+  * **Base** - This is Chromium's "Base" library, which contains a wide variety
+    of useful things used throughout Cobalt, Net, and Media. Cobalt uses a
+    combination of standard C++ containers (e.g. vector, string) and Base as the
+    foundation library for all of its code.
+  * **Other Third-party Libraries** - Most of these are venerable, straight-C,
+    open-source libraries that are commonly included in other open-source
+    software. Mostly format decoders and parsers (e.g. libpng, libxml2,
+    zlib). We fork these from Chromium, as we want them to be the most
+    battle-tested versions of these libraries.
+  * **Starboard/Glimp/ANGLE** - **Starboard** is the Cobalt porting
+    interface. One major difference between Cobalt and Chromium is that we have
+    created a hard straight-C porting layer, and ported ALL of the compiled
+    code, including Base and all third-party libraries, to use it instead of
+    directly using POSIX standard libraries, which are not consistent, even on
+    modern systems (see Android, Windows, MacOS X, and iOS). Additionally,
+    Starboard includes APIs that haven't been effectively standardized across
+    platforms, such as display Window creation, Input events, and Media
+    playback. **Glimp** is an OpenGL ES 2.0 implementation framework, built by
+    the Cobalt team directly on Starboard, designed to adapt proprietary 3D APIs
+    to GLES2. **ANGLE** Is a third-party library that adapts DirectX to GLES2,
+    similar to Glimp, but only for DirectX.
+
+Cobalt is like a flaky layered pastry - perhaps Baklava. It shouldn't be too
+difficult to rip the Web Implementation and Layout off the top, and just use the
+Renderer, or even to just use Base + Starboard + GLES2 as the basis of a new
+project.
+
+
+## The Cobalt Subset
+
+> Oh, we got both kinds of HTML tags,\
+> we got `<span>` and `<div>`!
+
+See the [Cobalt Subset specification](TODO) for more details on which tags,
+properties, and Web APIs are supported in Cobalt.
+
+*More to come.*
+
+
+## Interesting Source Locations
+
+All source locations are specified relative to `src/` (this directory).
+
+  * `base/` - Chromium's Base library. Contains common utilities, and a light
+    platform abstraction, which has been superceded in Cobalt by Starboard.
+  * `net/` - Chromium's Network library. Contains enough infrastructure to
+    support the network needs of an HTTP User-Agent (like Chromium or Cobalt),
+    an HTTP server, a DIAL server, and several abstractions for networking
+    primitives. Also contains SPDY and QUIC implementations.
+  * `media/` - Chromium's Media library. Contains all the code that parses,
+    processes, and manages buffers of video and audio data. Media decoding is
+    passed off to decoding hardware, wherever possible.
+  * `cobalt/` - The home of all Cobalt application code. This includes the Web
+    Implementation, Layout Engine, Renderer, and some other Cobalt-specific
+    features.
+      * `cobalt/build/` - The core build generation system, `gyp_cobalt`, and
+        configurations for supported platforms. (NOTE: This should eventually be
+        mostly moved into `starboard/`.)
+  * `starboard/` - Cobalt's porting layer. Please see Starboard's
+    [`README.md`](starboard/README.md) for more detailed information about
+    porting Starboard (and Cobalt) to a new platform.
+  * `third_party/` - Where all of Cobalt's third-party dependencies live. We
+    don't mean to be perjorative, we love our third-party libraries! This
+    location is dictated by Google OSS release management rules...
+      * `third_party/starboard/` - The location for third-party ports. This
+        directory will be scanned automatically by gyp_cobalt for available
+        Starboard ports.
+
+
+## Building and Running the Code
+
+Here's a quick and dirty guide to get to build the code on Linux.
+
+  1. Install the provided `depot_tools` archive into your favorite directory. It
+     has been slightly modified from Chromium's `depot_tools`.
+  2. Add that directory to the end of your `$PATH`.
+  3. Ensure you have these packages installed: `sudo apt-get install
+     libgles2-mesa-dev libpulse-dev libavformat-dev libavresample-dev
+     libasound2-dev libxrender-dev libxcomposite-dev`
+  4. Ensure you have the standard C++ header files installed
+     (e.g. `libstdc++-4.8-dev`).
+  5. Remove bison-3 and install bison-2.7, or just make sure that bison-2.7 is
+     before bison-3 on your `$PATH`. (NOTE: We plan on moving to bison-3 in the
+     future.)
+
+         $ sudo apt-get remove bison
+         $ sudo apt-get install m4
+         $ wget http://ftp.gnu.org/gnu/bison/bison-2.7.1.tar.gz
+         $ tar zxf bison-2.7.1.tar.gz
+         $ cd bison-2.7.1
+         $ sh configure && make && sudo make install
+         $ which bison
+         /usr/local/bin/bison
+         $ bison --version
+         bison (GNU Bison) 2.7.12-4996
+
+  6. (From this directory) run GYP:
+
+         cobalt/build/gyp_cobalt -C debug linux-x64x11
+
+  7. If you get a "clang not found" error, add the path to Cobalt's clang to
+     your `$PATH` and rerun `gyp_cobalt` as above. For example:
+     `/path/to/cobalt/src/third_party/llvm-build/Release+Asserts/bin`
+  8. Run Ninja:
+
+         ninja -C out/linux-x64x11_debug cobalt
+
+  9. Run Cobalt:
+
+         out/linux-x64x11_debug/cobalt [--url=<url>]
+
+      * If you want to use `http` instead of `https`, you must pass the
+        `--allow_http` flag to the Cobalt command-line.
+      * If you want to connect to an `https` host that doesn't have a
+        globally-validatable certificate, you must pass the
+        `--ignore_certificate_errors` flag to the Cobalt command-line.
+      * See `cobalt/browser/switches.cc` for more command-line options.
+
+
+## Build Types
+
+Cobalt has four build optimization levels, going from the slowest, least
+optimized, with the most debug information at the top (debug) to the fastest,
+most optimized, and with the least debug information at the bottom (gold):
+
+ | Type  | Optimizations | Logging | Asserts | Debug Info | Console  |
+ | :---- | :------------ | :------ | :------ | :--------- | :------- |
+ | debug | None          | Full    | Full    | Full       | Enabled  |
+ | devel | Full          | Full    | Full    | Full       | Enabled  |
+ | qa    | Full          | Limited | None    | None       | Enabled  |
+ | gold  | Full          | None    | None    | None       | Disabled |
+
+When building for release, you should always use a gold build for the final
+product.
+
+    $ cobalt/build/gyp_cobalt -C gold linux-x64x11
+    $ ninja -C out/linux-x64x11_gold cobalt
+    $ out/linux-x64x11_gold/cobalt
diff --git a/src/base/allocator/README b/src/base/allocator/README
new file mode 100644
index 0000000..ec8a707
--- /dev/null
+++ b/src/base/allocator/README
@@ -0,0 +1,59 @@
+Notes about the Chrome memory allocator.
+
+Background
+----------
+We use this library as a generic way to fork into any of several allocators.
+Currently we can, at runtime, switch between:
+   the default windows allocator
+   the windows low-fragmentation-heap
+   tcmalloc
+   jemalloc (the heap used most notably within Mozilla Firefox)
+
+The mechanism for hooking LIBCMT in windows is rather tricky.  The core
+problem is that by default, the windows library does not declare malloc and
+free as weak symbols.  Because of this, they cannot be overriden.  To work
+around this, we start with the LIBCMT.LIB, and manually remove all allocator
+related functions from it using the visual studio library tool.  Once removed,
+we can now link against the library and provide custom versions of the 
+allocator related functionality.
+
+
+Source code
+-----------
+This directory contains just the allocator (i.e. shim) layer that switches
+between the different underlying memory allocation implementations.
+
+The tcmalloc and jemalloc libraries originate outside of Chromium
+and exist in ../../third_party/tcmalloc and ../../third_party/jemalloc
+(currently, the actual locations are defined in the allocator.gyp file).
+The third party sources use a vendor-branch SCM pattern to track
+Chromium-specific changes independently from upstream changes.
+
+The general intent is to push local changes upstream so that over
+time we no longer need any forked files.
+
+
+Adding a new allocator
+----------------------
+Adding a new allocator requires definition of the following five functions:
+
+  extern "C" {
+    bool init();
+    void* malloc(size_t s);
+    void* realloc(void* p, size_t s);
+    void free(void* s);
+    size_t msize(void* p);
+  }
+
+All other allocation related functions (new/delete/calloc/etc) have been
+implemented generically to work across all allocators.
+
+
+Usage
+-----
+You can use the different allocators by setting the environment variable
+CHROME_ALLOCATOR to:
+   "tcmalloc"  - TC Malloc (default)
+   "jemalloc"  - JE Malloc
+   "winheap"   - Windows default heap
+   "winlfh"    - Windows Low-Fragmentation heap
diff --git a/src/base/allocator/allocator.gyp b/src/base/allocator/allocator.gyp
new file mode 100644
index 0000000..f5bda73
--- /dev/null
+++ b/src/base/allocator/allocator.gyp
@@ -0,0 +1,671 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'jemalloc_dir': '../../third_party/jemalloc/chromium',
+    'tcmalloc_dir': '../../third_party/tcmalloc/chromium',
+    'use_vtable_verify%': 0,
+  },
+  'targets': [
+    # Only executables and not libraries should depend on the
+    # allocator target; only the application (the final executable)
+    # knows what allocator makes sense.
+    {
+      'target_name': 'allocator',
+      'type': 'static_library',
+      # Make sure the allocation library is optimized to
+      # the hilt in official builds.
+      'variables': {
+        'optimize': 'max',
+      },
+      'include_dirs': [
+        '.',
+        '<(tcmalloc_dir)/src/base',
+        '<(tcmalloc_dir)/src',
+        '../..',
+      ],
+      'direct_dependent_settings': {
+        'configurations': {
+          'Common_Base': {
+            'msvs_settings': {
+              'VCLinkerTool': {
+                'IgnoreDefaultLibraryNames': ['libcmtd.lib', 'libcmt.lib'],
+                'AdditionalDependencies': [
+                  '<(SHARED_INTERMEDIATE_DIR)/allocator/libcmt.lib'
+                ],
+              },
+            },
+          },
+        },
+        'conditions': [
+          ['OS=="win"', {
+            'defines': [
+              'PERFTOOLS_DLL_DECL=',
+            ],
+          }],
+        ],
+      },
+      'sources': [
+        # Generated for our configuration from tcmalloc's build
+        # and checked in.
+        '<(tcmalloc_dir)/src/config.h',
+        '<(tcmalloc_dir)/src/config_linux.h',
+        '<(tcmalloc_dir)/src/config_win.h',
+
+        # all tcmalloc native and forked files
+        '<(tcmalloc_dir)/src/addressmap-inl.h',
+        '<(tcmalloc_dir)/src/base/abort.cc',
+        '<(tcmalloc_dir)/src/base/abort.h',
+        '<(tcmalloc_dir)/src/base/arm_instruction_set_select.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-arm-generic.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-arm-v6plus.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-macosx.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-windows.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-x86.cc',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-x86.h',
+        '<(tcmalloc_dir)/src/base/atomicops.h',
+        '<(tcmalloc_dir)/src/base/basictypes.h',
+        '<(tcmalloc_dir)/src/base/commandlineflags.h',
+        '<(tcmalloc_dir)/src/base/cycleclock.h',
+        # We don't list dynamic_annotations.c since its copy is already
+        # present in the dynamic_annotations target.
+        '<(tcmalloc_dir)/src/base/dynamic_annotations.h',
+        '<(tcmalloc_dir)/src/base/elf_mem_image.cc',
+        '<(tcmalloc_dir)/src/base/elf_mem_image.h',
+        '<(tcmalloc_dir)/src/base/elfcore.h',
+        '<(tcmalloc_dir)/src/base/googleinit.h',
+        '<(tcmalloc_dir)/src/base/linux_syscall_support.h',
+        '<(tcmalloc_dir)/src/base/linuxthreads.cc',
+        '<(tcmalloc_dir)/src/base/linuxthreads.h',
+        '<(tcmalloc_dir)/src/base/logging.cc',
+        '<(tcmalloc_dir)/src/base/logging.h',
+        '<(tcmalloc_dir)/src/base/low_level_alloc.cc',
+        '<(tcmalloc_dir)/src/base/low_level_alloc.h',
+        '<(tcmalloc_dir)/src/base/simple_mutex.h',
+        '<(tcmalloc_dir)/src/base/spinlock.cc',
+        '<(tcmalloc_dir)/src/base/spinlock.h',
+        '<(tcmalloc_dir)/src/base/spinlock_internal.cc',
+        '<(tcmalloc_dir)/src/base/spinlock_internal.h',
+        '<(tcmalloc_dir)/src/base/spinlock_linux-inl.h',
+        '<(tcmalloc_dir)/src/base/spinlock_posix-inl.h',
+        '<(tcmalloc_dir)/src/base/spinlock_win32-inl.h',
+        '<(tcmalloc_dir)/src/base/stl_allocator.h',
+        '<(tcmalloc_dir)/src/base/synchronization_profiling.h',
+        '<(tcmalloc_dir)/src/base/sysinfo.cc',
+        '<(tcmalloc_dir)/src/base/sysinfo.h',
+        '<(tcmalloc_dir)/src/base/thread_annotations.h',
+        '<(tcmalloc_dir)/src/base/thread_lister.c',
+        '<(tcmalloc_dir)/src/base/thread_lister.h',
+        '<(tcmalloc_dir)/src/base/vdso_support.cc',
+        '<(tcmalloc_dir)/src/base/vdso_support.h',
+        '<(tcmalloc_dir)/src/central_freelist.cc',
+        '<(tcmalloc_dir)/src/central_freelist.h',
+        '<(tcmalloc_dir)/src/common.cc',
+        '<(tcmalloc_dir)/src/common.h',
+        '<(tcmalloc_dir)/src/debugallocation.cc',
+        '<(tcmalloc_dir)/src/deep-heap-profile.cc',
+        '<(tcmalloc_dir)/src/deep-heap-profile.h',
+        '<(tcmalloc_dir)/src/free_list.cc',
+        '<(tcmalloc_dir)/src/free_list.h',
+        '<(tcmalloc_dir)/src/getpc.h',
+        '<(tcmalloc_dir)/src/gperftools/heap-checker.h',
+        '<(tcmalloc_dir)/src/gperftools/heap-profiler.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_extension.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_extension_c.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_hook.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_hook_c.h',
+        '<(tcmalloc_dir)/src/gperftools/profiler.h',
+        '<(tcmalloc_dir)/src/gperftools/stacktrace.h',
+        '<(tcmalloc_dir)/src/gperftools/tcmalloc.h',
+        '<(tcmalloc_dir)/src/heap-checker-bcad.cc',
+        '<(tcmalloc_dir)/src/heap-checker.cc',
+        '<(tcmalloc_dir)/src/heap-profile-table.cc',
+        '<(tcmalloc_dir)/src/heap-profile-table.h',
+        '<(tcmalloc_dir)/src/heap-profiler.cc',
+        '<(tcmalloc_dir)/src/internal_logging.cc',
+        '<(tcmalloc_dir)/src/internal_logging.h',
+        '<(tcmalloc_dir)/src/libc_override.h',
+        '<(tcmalloc_dir)/src/libc_override_gcc_and_weak.h',
+        '<(tcmalloc_dir)/src/libc_override_glibc.h',
+        '<(tcmalloc_dir)/src/libc_override_osx.h',
+        '<(tcmalloc_dir)/src/libc_override_redefine.h',
+        '<(tcmalloc_dir)/src/linked_list.h',
+        '<(tcmalloc_dir)/src/malloc_extension.cc',
+        '<(tcmalloc_dir)/src/malloc_hook-inl.h',
+        '<(tcmalloc_dir)/src/malloc_hook.cc',
+        '<(tcmalloc_dir)/src/malloc_hook_mmap_freebsd.h',
+        '<(tcmalloc_dir)/src/malloc_hook_mmap_linux.h',
+        '<(tcmalloc_dir)/src/maybe_threads.cc',
+        '<(tcmalloc_dir)/src/maybe_threads.h',
+        '<(tcmalloc_dir)/src/memfs_malloc.cc',
+        '<(tcmalloc_dir)/src/memory_region_map.cc',
+        '<(tcmalloc_dir)/src/memory_region_map.h',
+        '<(tcmalloc_dir)/src/packed-cache-inl.h',
+        '<(tcmalloc_dir)/src/page_heap.cc',
+        '<(tcmalloc_dir)/src/page_heap.h',
+        '<(tcmalloc_dir)/src/page_heap_allocator.h',
+        '<(tcmalloc_dir)/src/pagemap.h',
+        '<(tcmalloc_dir)/src/profile-handler.cc',
+        '<(tcmalloc_dir)/src/profile-handler.h',
+        '<(tcmalloc_dir)/src/profiledata.cc',
+        '<(tcmalloc_dir)/src/profiledata.h',
+        '<(tcmalloc_dir)/src/profiler.cc',
+        '<(tcmalloc_dir)/src/raw_printer.cc',
+        '<(tcmalloc_dir)/src/raw_printer.h',
+        '<(tcmalloc_dir)/src/sampler.cc',
+        '<(tcmalloc_dir)/src/sampler.h',
+        '<(tcmalloc_dir)/src/span.cc',
+        '<(tcmalloc_dir)/src/span.h',
+        '<(tcmalloc_dir)/src/stack_trace_table.cc',
+        '<(tcmalloc_dir)/src/stack_trace_table.h',
+        '<(tcmalloc_dir)/src/stacktrace.cc',
+        '<(tcmalloc_dir)/src/stacktrace_arm-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_config.h',
+        '<(tcmalloc_dir)/src/stacktrace_generic-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_libunwind-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_powerpc-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_win32-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_with_context.cc',
+        '<(tcmalloc_dir)/src/stacktrace_x86-inl.h',
+        '<(tcmalloc_dir)/src/static_vars.cc',
+        '<(tcmalloc_dir)/src/static_vars.h',
+        '<(tcmalloc_dir)/src/symbolize.cc',
+        '<(tcmalloc_dir)/src/symbolize.h',
+        '<(tcmalloc_dir)/src/system-alloc.cc',
+        '<(tcmalloc_dir)/src/system-alloc.h',
+        '<(tcmalloc_dir)/src/tcmalloc.cc',
+        '<(tcmalloc_dir)/src/tcmalloc_guard.h',
+        '<(tcmalloc_dir)/src/thread_cache.cc',
+        '<(tcmalloc_dir)/src/thread_cache.h',
+        '<(tcmalloc_dir)/src/windows/config.h',
+        '<(tcmalloc_dir)/src/windows/get_mangled_names.cc',
+        '<(tcmalloc_dir)/src/windows/gperftools/tcmalloc.h',
+        '<(tcmalloc_dir)/src/windows/ia32_modrm_map.cc',
+        '<(tcmalloc_dir)/src/windows/ia32_opcode_map.cc',
+        '<(tcmalloc_dir)/src/windows/mingw.h',
+        '<(tcmalloc_dir)/src/windows/mini_disassembler.cc',
+        '<(tcmalloc_dir)/src/windows/mini_disassembler.h',
+        '<(tcmalloc_dir)/src/windows/mini_disassembler_types.h',
+        '<(tcmalloc_dir)/src/windows/override_functions.cc',
+        '<(tcmalloc_dir)/src/windows/patch_functions.cc',
+        '<(tcmalloc_dir)/src/windows/port.cc',
+        '<(tcmalloc_dir)/src/windows/port.h',
+        '<(tcmalloc_dir)/src/windows/preamble_patcher.cc',
+        '<(tcmalloc_dir)/src/windows/preamble_patcher.h',
+        '<(tcmalloc_dir)/src/windows/preamble_patcher_with_stub.cc',
+
+        # jemalloc files
+        '<(jemalloc_dir)/jemalloc.c',
+        '<(jemalloc_dir)/jemalloc.h',
+        '<(jemalloc_dir)/ql.h',
+        '<(jemalloc_dir)/qr.h',
+        '<(jemalloc_dir)/rb.h',
+
+        'allocator_shim.cc',
+        'allocator_shim.h',
+        'debugallocation_shim.cc',
+        'generic_allocators.cc',
+        'win_allocator.cc',
+      ],
+      # sources! means that these are not compiled directly.
+      'sources!': [
+        # Included by allocator_shim.cc for maximal inlining.
+        'generic_allocators.cc',
+        'win_allocator.cc',
+
+        # Included by debugallocation_shim.cc.
+        '<(tcmalloc_dir)/src/debugallocation.cc',
+        '<(tcmalloc_dir)/src/tcmalloc.cc',
+
+        # We simply don't use these, but list them above so that IDE
+        # users can view the full available source for reference, etc.
+        '<(tcmalloc_dir)/src/addressmap-inl.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-macosx.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-x86-msvc.h',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-x86.cc',
+        '<(tcmalloc_dir)/src/base/atomicops-internals-x86.h',
+        '<(tcmalloc_dir)/src/base/atomicops.h',
+        '<(tcmalloc_dir)/src/base/basictypes.h',
+        '<(tcmalloc_dir)/src/base/commandlineflags.h',
+        '<(tcmalloc_dir)/src/base/cycleclock.h',
+        '<(tcmalloc_dir)/src/base/elf_mem_image.h',
+        '<(tcmalloc_dir)/src/base/elfcore.h',
+        '<(tcmalloc_dir)/src/base/googleinit.h',
+        '<(tcmalloc_dir)/src/base/linux_syscall_support.h',
+        '<(tcmalloc_dir)/src/base/simple_mutex.h',
+        '<(tcmalloc_dir)/src/base/spinlock_linux-inl.h',
+        '<(tcmalloc_dir)/src/base/spinlock_posix-inl.h',
+        '<(tcmalloc_dir)/src/base/spinlock_win32-inl.h',
+        '<(tcmalloc_dir)/src/base/stl_allocator.h',
+        '<(tcmalloc_dir)/src/base/thread_annotations.h',
+        '<(tcmalloc_dir)/src/getpc.h',
+        '<(tcmalloc_dir)/src/gperftools/heap-checker.h',
+        '<(tcmalloc_dir)/src/gperftools/heap-profiler.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_extension.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_extension_c.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_hook.h',
+        '<(tcmalloc_dir)/src/gperftools/malloc_hook_c.h',
+        '<(tcmalloc_dir)/src/gperftools/profiler.h',
+        '<(tcmalloc_dir)/src/gperftools/stacktrace.h',
+        '<(tcmalloc_dir)/src/gperftools/tcmalloc.h',
+        '<(tcmalloc_dir)/src/libc_override.h',
+        '<(tcmalloc_dir)/src/libc_override_gcc_and_weak.h',
+        '<(tcmalloc_dir)/src/libc_override_glibc.h',
+        '<(tcmalloc_dir)/src/libc_override_osx.h',
+        '<(tcmalloc_dir)/src/libc_override_redefine.h',
+        '<(tcmalloc_dir)/src/malloc_hook_mmap_freebsd.h',
+        '<(tcmalloc_dir)/src/malloc_hook_mmap_linux.h',
+        '<(tcmalloc_dir)/src/memfs_malloc.cc',
+        '<(tcmalloc_dir)/src/packed-cache-inl.h',
+        '<(tcmalloc_dir)/src/page_heap_allocator.h',
+        '<(tcmalloc_dir)/src/pagemap.h',
+        '<(tcmalloc_dir)/src/stacktrace_arm-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_config.h',
+        '<(tcmalloc_dir)/src/stacktrace_generic-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_libunwind-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_powerpc-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_win32-inl.h',
+        '<(tcmalloc_dir)/src/stacktrace_with_context.cc',
+        '<(tcmalloc_dir)/src/stacktrace_x86-inl.h',
+        '<(tcmalloc_dir)/src/tcmalloc_guard.h',
+        '<(tcmalloc_dir)/src/windows/config.h',
+        '<(tcmalloc_dir)/src/windows/gperftools/tcmalloc.h',
+        '<(tcmalloc_dir)/src/windows/get_mangled_names.cc',
+        '<(tcmalloc_dir)/src/windows/ia32_modrm_map.cc',
+        '<(tcmalloc_dir)/src/windows/ia32_opcode_map.cc',
+        '<(tcmalloc_dir)/src/windows/mingw.h',
+        '<(tcmalloc_dir)/src/windows/mini_disassembler.cc',
+        '<(tcmalloc_dir)/src/windows/mini_disassembler.h',
+        '<(tcmalloc_dir)/src/windows/mini_disassembler_types.h',
+        '<(tcmalloc_dir)/src/windows/override_functions.cc',
+        '<(tcmalloc_dir)/src/windows/patch_functions.cc',
+        '<(tcmalloc_dir)/src/windows/preamble_patcher.cc',
+        '<(tcmalloc_dir)/src/windows/preamble_patcher.h',
+        '<(tcmalloc_dir)/src/windows/preamble_patcher_with_stub.cc',
+      ],
+      'dependencies': [
+        '../third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+      ],
+      'msvs_settings': {
+        # TODO(sgk):  merge this with build/common.gypi settings
+        'VCLibrarianTool': {
+          'AdditionalOptions': ['/ignore:4006,4221'],
+          'AdditionalLibraryDirectories':
+            ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
+        },
+        'VCLinkerTool': {
+          'AdditionalOptions': ['/ignore:4006'],
+        },
+      },
+      'configurations': {
+        'Debug_Base': {
+          'msvs_settings': {
+            'VCCLCompilerTool': {
+              'RuntimeLibrary': '0',
+            },
+          },
+          'variables': {
+            # Provide a way to force disable debugallocation in Debug builds,
+            # e.g. for profiling (it's more rare to profile Debug builds,
+            # but people sometimes need to do that).
+            'disable_debugallocation%': 1,
+          },
+          'conditions': [
+            ['disable_debugallocation==0', {
+              'defines': [
+                # Use debugallocation for Debug builds to catch problems early
+                # and cleanly, http://crbug.com/30715 .
+                'TCMALLOC_FOR_DEBUGALLOCATION',
+              ],
+            }],
+          ],
+        },
+      },
+      'conditions': [
+        ['OS=="linux" and clang_type_profiler==1', {
+          'dependencies': [
+            'type_profiler_tcmalloc',
+          ],
+          # It is undoing dependencies and cflags_cc for type_profiler which
+          # build/common.gypi injects into all targets.
+          'dependencies!': [
+            'type_profiler',
+          ],
+          'cflags_cc!': [
+            '-fintercept-allocation-functions',
+          ],
+        }],
+        ['OS=="win"', {
+          'defines': [
+            'PERFTOOLS_DLL_DECL=',
+          ],
+          'defines!': [
+            # tcmalloc source files unconditionally define this, remove it from
+            # the list of defines that common.gypi defines globally.
+            'NOMINMAX',
+          ],
+          'dependencies': [
+            'libcmt',
+          ],
+          'include_dirs': [
+            '<(jemalloc_dir)',
+            '<(tcmalloc_dir)/src/windows',
+          ],
+          'sources!': [
+            '<(tcmalloc_dir)/src/base/elf_mem_image.cc',
+            '<(tcmalloc_dir)/src/base/elf_mem_image.h',
+            '<(tcmalloc_dir)/src/base/linuxthreads.cc',
+            '<(tcmalloc_dir)/src/base/linuxthreads.h',
+            '<(tcmalloc_dir)/src/base/vdso_support.cc',
+            '<(tcmalloc_dir)/src/base/vdso_support.h',
+            '<(tcmalloc_dir)/src/maybe_threads.cc',
+            '<(tcmalloc_dir)/src/maybe_threads.h',
+            '<(tcmalloc_dir)/src/symbolize.h',
+            '<(tcmalloc_dir)/src/system-alloc.cc',
+            '<(tcmalloc_dir)/src/system-alloc.h',
+
+            # included by allocator_shim.cc
+            'debugallocation_shim.cc',
+
+            # heap-profiler/checker/cpuprofiler
+            '<(tcmalloc_dir)/src/base/thread_lister.c',
+            '<(tcmalloc_dir)/src/base/thread_lister.h',
+            '<(tcmalloc_dir)/src/deep-heap-profile.cc',
+            '<(tcmalloc_dir)/src/deep-heap-profile.h',
+            '<(tcmalloc_dir)/src/heap-checker-bcad.cc',
+            '<(tcmalloc_dir)/src/heap-checker.cc',
+            '<(tcmalloc_dir)/src/heap-profiler.cc',
+            '<(tcmalloc_dir)/src/heap-profile-table.cc',
+            '<(tcmalloc_dir)/src/heap-profile-table.h',
+            '<(tcmalloc_dir)/src/memory_region_map.cc',
+            '<(tcmalloc_dir)/src/memory_region_map.h',
+            '<(tcmalloc_dir)/src/profiledata.cc',
+            '<(tcmalloc_dir)/src/profiledata.h',
+            '<(tcmalloc_dir)/src/profile-handler.cc',
+            '<(tcmalloc_dir)/src/profile-handler.h',
+            '<(tcmalloc_dir)/src/profiler.cc',
+          ],
+        }],
+        ['OS=="linux" or OS=="freebsd" or OS=="solaris"', {
+          'sources!': [
+            '<(tcmalloc_dir)/src/system-alloc.h',
+            '<(tcmalloc_dir)/src/windows/port.cc',
+            '<(tcmalloc_dir)/src/windows/port.h',
+
+            # TODO(willchan): Support allocator shim later on.
+            'allocator_shim.cc',
+
+            # TODO(willchan): support jemalloc on other platforms
+            # jemalloc files
+            '<(jemalloc_dir)/jemalloc.c',
+            '<(jemalloc_dir)/jemalloc.h',
+            '<(jemalloc_dir)/ql.h',
+            '<(jemalloc_dir)/qr.h',
+            '<(jemalloc_dir)/rb.h',
+
+          ],
+          # We enable all warnings by default, but upstream disables a few.
+          # Keep "-Wno-*" flags in sync with upstream by comparing against:
+          # http://code.google.com/p/google-perftools/source/browse/trunk/Makefile.am
+          'cflags': [
+            '-Wno-sign-compare',
+            '-Wno-unused-result',
+          ],
+          'cflags!': [
+            '-fvisibility=hidden',
+          ],
+          'link_settings': {
+            'ldflags': [
+              # Don't let linker rip this symbol out, otherwise the heap&cpu
+              # profilers will not initialize properly on startup.
+              '-Wl,-uIsHeapProfilerRunning,-uProfilerStart',
+              # Do the same for heap leak checker.
+              '-Wl,-u_Z21InitialMallocHook_NewPKvj,-u_Z22InitialMallocHook_MMapPKvS0_jiiix,-u_Z22InitialMallocHook_SbrkPKvi',
+              '-Wl,-u_Z21InitialMallocHook_NewPKvm,-u_Z22InitialMallocHook_MMapPKvS0_miiil,-u_Z22InitialMallocHook_SbrkPKvl',
+              '-Wl,-u_ZN15HeapLeakChecker12IgnoreObjectEPKv,-u_ZN15HeapLeakChecker14UnIgnoreObjectEPKv',
+          ]},
+        }],
+        [ 'use_vtable_verify==1', {
+          'cflags': [
+            '-fvtable-verify=preinit',
+          ],
+        }],
+        [ 'linux_keep_shadow_stacks==1', {
+          'sources': [
+            '<(tcmalloc_dir)/src/linux_shadow_stacks.cc',
+            '<(tcmalloc_dir)/src/linux_shadow_stacks.h',
+            '<(tcmalloc_dir)/src/stacktrace_shadow-inl.h',
+          ],
+          'cflags': [
+            '-finstrument-functions',
+          ],
+          'defines': [
+            'KEEP_SHADOW_STACKS',
+          ],
+        }],
+        [ 'linux_use_heapchecker==0', {
+          # Do not compile and link the heapchecker source.
+          'sources!': [
+            '<(tcmalloc_dir)/src/heap-checker-bcad.cc',
+            '<(tcmalloc_dir)/src/heap-checker.cc',
+          ],
+          # Disable the heap checker in tcmalloc.
+          'defines': [
+            'NO_HEAP_CHECK',
+           ],
+        }],
+        [ 'clang==1', {
+          'cflags': [
+            '-Wno-non-literal-null-conversion',
+          ],
+        }],
+        ['order_profiling != 0', {
+          'target_conditions' : [
+            ['_toolset=="target"', {
+              'cflags!': [ '-finstrument-functions' ],
+            }],
+          ],
+        }],
+      ],
+    },
+    {
+      # This library is linked in to src/base.gypi:base and allocator_unittests
+      # It can't depend on either and nothing else should depend on it - all
+      # other code should use the interfaced provided by base.
+      'target_name': 'allocator_extension_thunks',
+      'type': 'static_library',
+      'sources': [
+        'allocator_extension_thunks.cc',
+        'allocator_extension_thunks.h',
+      ],
+      'toolsets': ['host', 'target'],
+      'include_dirs': [
+        '../../'
+      ],
+      'conditions': [
+        ['OS=="linux" and clang_type_profiler==1', {
+          # It is undoing dependencies and cflags_cc for type_profiler which
+          # build/common.gypi injects into all targets.
+          'dependencies!': [
+            'type_profiler',
+          ],
+          'cflags_cc!': [
+            '-fintercept-allocation-functions',
+          ],
+        }],
+      ],
+    },
+   ],
+  'conditions': [
+    ['OS=="win"', {
+      'targets': [
+        {
+          'target_name': 'libcmt',
+          'type': 'none',
+          'actions': [
+            {
+              'action_name': 'libcmt',
+              'inputs': [
+                'prep_libc.py',
+              ],
+              'outputs': [
+                '<(SHARED_INTERMEDIATE_DIR)/allocator/libcmt.lib',
+              ],
+              'action': [
+                'python',
+                'prep_libc.py',
+                '$(VCInstallDir)lib',
+                '<(SHARED_INTERMEDIATE_DIR)/allocator',
+              ],
+            },
+          ],
+        },
+        {
+          'target_name': 'allocator_unittests',
+          'type': 'executable',
+          'dependencies': [
+            'allocator',
+            'allocator_extension_thunks',
+            '../../testing/gtest.gyp:gtest',
+          ],
+          'include_dirs': [
+            '.',
+            '<(tcmalloc_dir)/src/base',
+            '<(tcmalloc_dir)/src',
+            '../..',
+          ],
+          'sources': [
+            'allocator_unittests.cc',
+            '../profiler/alternate_timer.cc',
+            '../profiler/alternate_timer.h',
+          ],
+        },
+        {
+          'target_name': 'allocator_extension_thunks_win64',
+          'type': 'static_library',
+          'sources': [
+            'allocator_extension_thunks.cc',
+            'allocator_extension_thunks.h',
+          ],
+          'toolsets': ['host', 'target'],
+          'include_dirs': [
+            '../../'
+          ],
+          'configurations': {
+            'Common_Base': {
+              'msvs_target_platform': 'x64',
+            },
+          },
+        },
+      {
+        'target_name': 'tcmalloc_unittest',
+        'type': 'executable',
+        'sources': [
+          'tcmalloc_unittest.cc',
+        ],
+        'include_dirs': [
+          '../..',
+          # For constants of TCMalloc.
+          '<(tcmalloc_dir)/src',
+        ],
+        'dependencies': [
+          '../../testing/gtest.gyp:gtest',
+          '../base.gyp:base',
+          'allocator',
+        ],
+      },
+      ],
+    }],
+    ['OS=="linux" and clang_type_profiler==1', {
+      # Some targets in this section undo dependencies and cflags_cc for
+      # type_profiler which build/common.gypi injects into all targets.
+      'targets': [
+        {
+          'target_name': 'type_profiler',
+          'type': 'static_library',
+          'dependencies!': [
+            'type_profiler',
+          ],
+          'cflags_cc!': [
+            '-fintercept-allocation-functions',
+          ],
+          'include_dirs': [
+            '../..',
+          ],
+          'sources': [
+            'type_profiler.cc',
+            'type_profiler.h',
+            'type_profiler_control.h',
+          ],
+          'toolsets': ['host', 'target'],
+        },
+        {
+          'target_name': 'type_profiler_tcmalloc',
+          'type': 'static_library',
+          'dependencies!': [
+            'type_profiler',
+          ],
+          'cflags_cc!': [
+            '-fintercept-allocation-functions',
+          ],
+          'include_dirs': [
+            '<(tcmalloc_dir)/src',
+            '../..',
+          ],
+          'sources': [
+            'type_profiler_tcmalloc.cc',
+            'type_profiler_tcmalloc.h',
+            '<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
+            '<(tcmalloc_dir)/src/type_profiler_map.cc',
+          ],
+        },
+        {
+          'target_name': 'type_profiler_unittests',
+          'type': 'executable',
+          'dependencies': [
+            '../../testing/gtest.gyp:gtest',
+            '../base.gyp:base',
+            'allocator',
+            'type_profiler_tcmalloc',
+          ],
+          'include_dirs': [
+            '../..',
+          ],
+          'sources': [
+            'type_profiler_control.cc',
+            'type_profiler_control.h',
+            'type_profiler_unittests.cc',
+          ],
+        },
+        {
+          'target_name': 'type_profiler_map_unittests',
+          'type': 'executable',
+          'dependencies': [
+            '../../testing/gtest.gyp:gtest',
+            '../base.gyp:base',
+            'allocator',
+          ],
+          'dependencies!': [
+            'type_profiler',
+          ],
+          'cflags_cc!': [
+            '-fintercept-allocation-functions',
+          ],
+          'include_dirs': [
+            '<(tcmalloc_dir)/src',
+            '../..',
+          ],
+          'sources': [
+            'type_profiler_map_unittests.cc',
+            '<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
+            '<(tcmalloc_dir)/src/type_profiler_map.cc',
+          ],
+        },
+      ],
+    }],
+  ],
+}
diff --git a/src/base/allocator/allocator_extension.cc b/src/base/allocator/allocator_extension.cc
new file mode 100644
index 0000000..83e460a
--- /dev/null
+++ b/src/base/allocator/allocator_extension.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/allocator/allocator_extension.h"
+
+#include "base/logging.h"
+
+namespace base {
+namespace allocator {
+
+bool GetAllocatorWasteSize(size_t* size) {
+  thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function =
+      thunks::GetGetAllocatorWasteSizeFunction();
+  return get_allocator_waste_size_function != NULL &&
+         get_allocator_waste_size_function(size);
+}
+
+void GetStats(char* buffer, int buffer_length) {
+  DCHECK_GT(buffer_length, 0);
+  thunks::GetStatsFunction get_stats_function = thunks::GetGetStatsFunction();
+  if (get_stats_function)
+    get_stats_function(buffer, buffer_length);
+  else
+    buffer[0] = '\0';
+}
+
+void ReleaseFreeMemory() {
+  thunks::ReleaseFreeMemoryFunction release_free_memory_function =
+      thunks::GetReleaseFreeMemoryFunction();
+  if (release_free_memory_function)
+    release_free_memory_function();
+}
+
+void SetGetAllocatorWasteSizeFunction(
+    thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function) {
+  DCHECK_EQ(thunks::GetGetAllocatorWasteSizeFunction(),
+            reinterpret_cast<thunks::GetAllocatorWasteSizeFunction>(NULL));
+  thunks::SetGetAllocatorWasteSizeFunction(get_allocator_waste_size_function);
+}
+
+void SetGetStatsFunction(thunks::GetStatsFunction get_stats_function) {
+  DCHECK_EQ(thunks::GetGetStatsFunction(),
+            reinterpret_cast<thunks::GetStatsFunction>(NULL));
+  thunks::SetGetStatsFunction(get_stats_function);
+}
+
+void SetReleaseFreeMemoryFunction(
+    thunks::ReleaseFreeMemoryFunction release_free_memory_function) {
+  DCHECK_EQ(thunks::GetReleaseFreeMemoryFunction(),
+            reinterpret_cast<thunks::ReleaseFreeMemoryFunction>(NULL));
+  thunks::SetReleaseFreeMemoryFunction(release_free_memory_function);
+}
+
+}  // namespace allocator
+}  // namespace base
diff --git a/src/base/allocator/allocator_extension.h b/src/base/allocator/allocator_extension.h
new file mode 100644
index 0000000..de3119f
--- /dev/null
+++ b/src/base/allocator/allocator_extension.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H
+#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H
+
+#include <stddef.h> // for size_t
+
+#include "base/allocator/allocator_extension_thunks.h"
+#include "base/base_export.h"
+#include "build/build_config.h"
+
+namespace base {
+namespace allocator {
+
+// Request the allocator to report value of its waste memory size.
+// Waste size corresponds to memory that has been allocated from the OS but
+// not passed up to the application. It e.g. includes memory retained by free
+// lists, internal data, chunks padding, etc.
+//
+// |size| pointer to the returned value, must be not NULL.
+// Returns true if the value has been returned, false otherwise.
+BASE_EXPORT bool GetAllocatorWasteSize(size_t* size);
+
+// Request that the allocator print a human-readable description of the current
+// state of the allocator into a null-terminated string in the memory segment
+// buffer[0,buffer_length-1].
+//
+// |buffer| must point to a valid piece of memory
+// |buffer_length| must be > 0.
+BASE_EXPORT void GetStats(char* buffer, int buffer_length);
+
+// Request that the allocator release any free memory it knows about to the
+// system.
+BASE_EXPORT void ReleaseFreeMemory();
+
+
+// These settings allow specifying a callback used to implement the allocator
+// extension functions.  These are optional, but if set they must only be set
+// once.  These will typically called in an allocator-specific initialization
+// routine.
+//
+// No threading promises are made.  The caller is responsible for making sure
+// these pointers are set before any other threads attempt to call the above
+// functions.
+BASE_EXPORT void SetGetAllocatorWasteSizeFunction(
+    thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function);
+
+BASE_EXPORT void SetGetStatsFunction(
+    thunks::GetStatsFunction get_stats_function);
+
+BASE_EXPORT void SetReleaseFreeMemoryFunction(
+    thunks::ReleaseFreeMemoryFunction release_free_memory_function);
+
+}  // namespace allocator
+}  // namespace base
+
+#endif
diff --git a/src/base/allocator/allocator_extension_thunks.cc b/src/base/allocator/allocator_extension_thunks.cc
new file mode 100644
index 0000000..e4024fb
--- /dev/null
+++ b/src/base/allocator/allocator_extension_thunks.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/allocator/allocator_extension_thunks.h"
+
+#include <cstddef> // for NULL
+
+namespace base {
+namespace allocator {
+namespace thunks {
+
+// This slightly odd translation unit exists because of the peculularity of how
+// allocator_unittests work on windows.  That target has to perform
+// tcmalloc-specific initialization on windows, but it cannot depend on base
+// otherwise. This target sits in the middle - base and allocator_unittests
+// can depend on it. This file can't depend on anything else in base, including
+// logging.
+
+static GetAllocatorWasteSizeFunction g_get_allocator_waste_size_function = NULL;
+static GetStatsFunction g_get_stats_function = NULL;
+static ReleaseFreeMemoryFunction g_release_free_memory_function = NULL;
+
+void SetGetAllocatorWasteSizeFunction(
+    GetAllocatorWasteSizeFunction get_allocator_waste_size_function) {
+  g_get_allocator_waste_size_function = get_allocator_waste_size_function;
+}
+
+GetAllocatorWasteSizeFunction GetGetAllocatorWasteSizeFunction() {
+  return g_get_allocator_waste_size_function;
+}
+
+void SetGetStatsFunction(GetStatsFunction get_stats_function) {
+  g_get_stats_function = get_stats_function;
+}
+
+GetStatsFunction GetGetStatsFunction() {
+  return g_get_stats_function;
+}
+
+void SetReleaseFreeMemoryFunction(
+    ReleaseFreeMemoryFunction release_free_memory_function) {
+  g_release_free_memory_function = release_free_memory_function;
+}
+
+ReleaseFreeMemoryFunction GetReleaseFreeMemoryFunction() {
+  return g_release_free_memory_function;
+}
+
+}  // namespace thunks
+}  // namespace allocator
+}  // namespace base
diff --git a/src/base/allocator/allocator_extension_thunks.h b/src/base/allocator/allocator_extension_thunks.h
new file mode 100644
index 0000000..1e97a84
--- /dev/null
+++ b/src/base/allocator/allocator_extension_thunks.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H
+#define BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H
+
+#include <stddef.h> // for size_t
+
+namespace base {
+namespace allocator {
+namespace thunks {
+
+// WARNING: You probably don't want to use this file unless you are routing a
+// new allocator extension from a specific allocator implementation to base.
+// See allocator_extension.h to see the interface that base exports.
+
+typedef bool (*GetAllocatorWasteSizeFunction)(size_t* size);
+void SetGetAllocatorWasteSizeFunction(
+    GetAllocatorWasteSizeFunction get_allocator_waste_size_function);
+GetAllocatorWasteSizeFunction GetGetAllocatorWasteSizeFunction();
+
+typedef void (*GetStatsFunction)(char* buffer, int buffer_length);
+void SetGetStatsFunction(GetStatsFunction get_stats_function);
+GetStatsFunction GetGetStatsFunction();
+
+typedef void (*ReleaseFreeMemoryFunction)();
+void SetReleaseFreeMemoryFunction(
+    ReleaseFreeMemoryFunction release_free_memory_function);
+ReleaseFreeMemoryFunction GetReleaseFreeMemoryFunction();
+
+}  // namespace thunks
+}  // namespace allocator
+}  // namespace base
+
+#endif
diff --git a/src/base/allocator/allocator_shim.cc b/src/base/allocator/allocator_shim.cc
new file mode 100644
index 0000000..6e41327
--- /dev/null
+++ b/src/base/allocator/allocator_shim.cc
@@ -0,0 +1,431 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/allocator/allocator_shim.h"
+
+#include <config.h>
+#include "base/allocator/allocator_extension_thunks.h"
+#include "base/profiler/alternate_timer.h"
+#include "base/sysinfo.h"
+#include "jemalloc.h"
+
+// When defined, different heap allocators can be used via an environment
+// variable set before running the program.  This may reduce the amount
+// of inlining that we get with malloc/free/etc.  Disabling makes it
+// so that only tcmalloc can be used.
+#define ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+
+// TODO(mbelshe): Ensure that all calls to tcmalloc have the proper call depth
+// from the "user code" so that debugging tools (HeapChecker) can work.
+
+// __THROW is defined in glibc systems.  It means, counter-intuitively,
+// "This function will never throw an exception."  It's an optional
+// optimization tool, but we may need to use it to match glibc prototypes.
+#ifndef __THROW    // I guess we're not on a glibc system
+# define __THROW   // __THROW is just an optimization, so ok to make it ""
+#endif
+
+// new_mode behaves similarly to MSVC's _set_new_mode.
+// If flag is 0 (default), calls to malloc will behave normally.
+// If flag is 1, calls to malloc will behave like calls to new,
+// and the std_new_handler will be invoked on failure.
+// Can be set by calling _set_new_mode().
+static int new_mode = 0;
+
+typedef enum {
+  TCMALLOC,    // TCMalloc is the default allocator.
+  JEMALLOC,    // JEMalloc.
+  WINHEAP,  // Windows Heap (standard Windows allocator).
+  WINLFH,      // Windows LFH Heap.
+} Allocator;
+
+// This is the default allocator. This value can be changed at startup by
+// specifying environment variables shown below it.
+// See SetupSubprocessAllocator() to specify a default secondary (subprocess)
+// allocator.
+// TODO(jar): Switch to using TCMALLOC for the renderer as well.
+static Allocator allocator = TCMALLOC;
+
+// The names of the environment variables that can optionally control the
+// selection of the allocator.  The primary may be used to control overall
+// allocator selection, and the secondary can be used to specify an allocator
+// to use in sub-processes.
+static const char primary_name[] = "CHROME_ALLOCATOR";
+static const char secondary_name[] = "CHROME_ALLOCATOR_2";
+
+// We include tcmalloc and the win_allocator to get as much inlining as
+// possible.
+#include "debugallocation_shim.cc"
+#include "win_allocator.cc"
+
+// Forward declarations from jemalloc.
+extern "C" {
+void* je_malloc(size_t s);
+void* je_realloc(void* p, size_t s);
+void je_free(void* s);
+size_t je_msize(void* p);
+bool je_malloc_init_hard();
+void* je_memalign(size_t a, size_t s);
+}
+
+extern "C" {
+
+// Call the new handler, if one has been set.
+// Returns true on successfully calling the handler, false otherwise.
+inline bool call_new_handler(bool nothrow) {
+  // Get the current new handler.  NB: this function is not
+  // thread-safe.  We make a feeble stab at making it so here, but
+  // this lock only protects against tcmalloc interfering with
+  // itself, not with other libraries calling set_new_handler.
+  std::new_handler nh;
+  {
+    SpinLockHolder h(&set_new_handler_lock);
+    nh = std::set_new_handler(0);
+    (void) std::set_new_handler(nh);
+  }
+#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+  if (!nh)
+    return false;
+  // Since exceptions are disabled, we don't really know if new_handler
+  // failed.  Assume it will abort if it fails.
+  (*nh)();
+  return false;  // break out of the retry loop.
+#else
+  // If no new_handler is established, the allocation failed.
+  if (!nh) {
+    if (nothrow)
+      return 0;
+    throw std::bad_alloc();
+  }
+  // Otherwise, try the new_handler.  If it returns, retry the
+  // allocation.  If it throws std::bad_alloc, fail the allocation.
+  // if it throws something else, don't interfere.
+  try {
+    (*nh)();
+  } catch (const std::bad_alloc&) {
+    if (!nothrow)
+      throw;
+    return true;
+  }
+#endif  // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+}
+
+void* malloc(size_t size) __THROW {
+  void* ptr;
+  for (;;) {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+    switch (allocator) {
+      case JEMALLOC:
+        ptr = je_malloc(size);
+        break;
+      case WINHEAP:
+      case WINLFH:
+        ptr = win_heap_malloc(size);
+        break;
+      case TCMALLOC:
+      default:
+        ptr = do_malloc(size);
+        break;
+    }
+#else
+    // TCMalloc case.
+    ptr = do_malloc(size);
+#endif
+    if (ptr)
+      return ptr;
+
+    if (!new_mode || !call_new_handler(true))
+      break;
+  }
+  return ptr;
+}
+
+void free(void* p) __THROW {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+  switch (allocator) {
+    case JEMALLOC:
+      je_free(p);
+      return;
+    case WINHEAP:
+    case WINLFH:
+      win_heap_free(p);
+      return;
+  }
+#endif
+  // TCMalloc case.
+  do_free(p);
+}
+
+void* realloc(void* ptr, size_t size) __THROW {
+  // Webkit is brittle for allocators that return NULL for malloc(0).  The
+  // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure
+  // to call malloc for this case.
+  if (!ptr)
+    return malloc(size);
+
+  void* new_ptr;
+  for (;;) {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+    switch (allocator) {
+      case JEMALLOC:
+        new_ptr = je_realloc(ptr, size);
+        break;
+      case WINHEAP:
+      case WINLFH:
+        new_ptr = win_heap_realloc(ptr, size);
+        break;
+      case TCMALLOC:
+      default:
+        new_ptr = do_realloc(ptr, size);
+        break;
+    }
+#else
+    // TCMalloc case.
+    new_ptr = do_realloc(ptr, size);
+#endif
+
+    // Subtle warning:  NULL return does not alwas indicate out-of-memory.  If
+    // the requested new size is zero, realloc should free the ptr and return
+    // NULL.
+    if (new_ptr || !size)
+      return new_ptr;
+    if (!new_mode || !call_new_handler(true))
+      break;
+  }
+  return new_ptr;
+}
+
+// TODO(mbelshe): Implement this for other allocators.
+void malloc_stats(void) __THROW {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+  switch (allocator) {
+    case JEMALLOC:
+      // No stats.
+      return;
+    case WINHEAP:
+    case WINLFH:
+      // No stats.
+      return;
+  }
+#endif
+  tc_malloc_stats();
+}
+
+#ifdef WIN32
+
+extern "C" size_t _msize(void* p) {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+  switch (allocator) {
+    case JEMALLOC:
+      return je_msize(p);
+    case WINHEAP:
+    case WINLFH:
+      return win_heap_msize(p);
+  }
+#endif
+  return MallocExtension::instance()->GetAllocatedSize(p);
+}
+
+// This is included to resolve references from libcmt.
+extern "C" intptr_t _get_heap_handle() {
+  return 0;
+}
+
+static bool get_allocator_waste_size_thunk(size_t* size) {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+  switch (allocator) {
+    case JEMALLOC:
+    case WINHEAP:
+    case WINLFH:
+      // TODO(alexeif): Implement for allocators other than tcmalloc.
+      return false;
+  }
+#endif
+  size_t heap_size, allocated_bytes, unmapped_bytes;
+  MallocExtension* ext = MallocExtension::instance();
+  if (ext->GetNumericProperty("generic.heap_size", &heap_size) &&
+      ext->GetNumericProperty("generic.current_allocated_bytes",
+                              &allocated_bytes) &&
+      ext->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes",
+                              &unmapped_bytes)) {
+    *size = heap_size - allocated_bytes - unmapped_bytes;
+    return true;
+  }
+  return false;
+}
+
+static void get_stats_thunk(char* buffer, int buffer_length) {
+  MallocExtension::instance()->GetStats(buffer, buffer_length);
+}
+
+static void release_free_memory_thunk() {
+  MallocExtension::instance()->ReleaseFreeMemory();
+}
+
+// The CRT heap initialization stub.
+extern "C" int _heap_init() {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+  const char* environment_value = GetenvBeforeMain(primary_name);
+  if (environment_value) {
+    if (!stricmp(environment_value, "jemalloc"))
+      allocator = JEMALLOC;
+    else if (!stricmp(environment_value, "winheap"))
+      allocator = WINHEAP;
+    else if (!stricmp(environment_value, "winlfh"))
+      allocator = WINLFH;
+    else if (!stricmp(environment_value, "tcmalloc"))
+      allocator = TCMALLOC;
+  }
+
+  switch (allocator) {
+    case JEMALLOC:
+      return je_malloc_init_hard() ? 0 : 1;
+    case WINHEAP:
+      return win_heap_init(false) ? 1 : 0;
+    case WINLFH:
+      return win_heap_init(true) ? 1 : 0;
+    case TCMALLOC:
+    default:
+      // fall through
+      break;
+  }
+#endif
+  // Initializing tcmalloc.
+  // We intentionally leak this object.  It lasts for the process
+  // lifetime.  Trying to teardown at _heap_term() is so late that
+  // you can't do anything useful anyway.
+  new TCMallocGuard();
+
+  // Provide optional hook for monitoring allocation quantities on a per-thread
+  // basis.  Only set the hook if the environment indicates this needs to be
+  // enabled.
+  const char* profiling =
+      GetenvBeforeMain(tracked_objects::kAlternateProfilerTime);
+  if (profiling && *profiling == '1') {
+    tracked_objects::SetAlternateTimeSource(
+        tcmalloc::ThreadCache::GetBytesAllocatedOnCurrentThread,
+        tracked_objects::TIME_SOURCE_TYPE_TCMALLOC);
+  }
+
+  base::allocator::thunks::SetGetAllocatorWasteSizeFunction(
+      get_allocator_waste_size_thunk);
+  base::allocator::thunks::SetGetStatsFunction(get_stats_thunk);
+  base::allocator::thunks::SetReleaseFreeMemoryFunction(
+      release_free_memory_thunk);
+
+  return 1;
+}
+
+// The CRT heap cleanup stub.
+extern "C" void _heap_term() {}
+
+// We set this to 1 because part of the CRT uses a check of _crtheap != 0
+// to test whether the CRT has been initialized.  Once we've ripped out
+// the allocators from libcmt, we need to provide this definition so that
+// the rest of the CRT is still usable.
+extern "C" void* _crtheap = reinterpret_cast<void*>(1);
+
+// Provide support for aligned memory through Windows only _aligned_malloc().
+void* _aligned_malloc(size_t size, size_t alignment) {
+  // _aligned_malloc guarantees parameter validation, so do so here.  These
+  // checks are somewhat stricter than _aligned_malloc() since we're effectively
+  // using memalign() under the hood.
+  DCHECK_GT(size, 0U);
+  DCHECK_EQ(alignment & (alignment - 1), 0U);
+  DCHECK_EQ(alignment % sizeof(void*), 0U);
+
+  void* ptr;
+  for (;;) {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+    switch (allocator) {
+      case JEMALLOC:
+        ptr = je_memalign(alignment, size);
+        break;
+      case WINHEAP:
+      case WINLFH:
+        ptr = win_heap_memalign(alignment, size);
+        break;
+      case TCMALLOC:
+      default:
+        ptr = tc_memalign(alignment, size);
+        break;
+    }
+#else
+    // TCMalloc case.
+    ptr = tc_memalign(alignment, size);
+#endif
+    if (ptr) {
+      // Sanity check alignment.
+      DCHECK_EQ(reinterpret_cast<uintptr_t>(ptr) & (alignment - 1), 0U);
+      return ptr;
+    }
+
+    if (!new_mode || !call_new_handler(true))
+      break;
+  }
+  return ptr;
+}
+
+void _aligned_free(void* p) {
+  // Both JEMalloc and TCMalloc return pointers from memalign() that are safe to
+  // use with free().  Pointers allocated with win_heap_memalign() MUST be freed
+  // via win_heap_memalign_free() since the aligned pointer is not the real one.
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+  switch (allocator) {
+    case JEMALLOC:
+      je_free(p);
+      return;
+    case WINHEAP:
+    case WINLFH:
+      win_heap_memalign_free(p);
+      return;
+  }
+#endif
+  // TCMalloc case.
+  do_free(p);
+}
+
+#endif  // WIN32
+
+#include "generic_allocators.cc"
+
+}  // extern C
+
+namespace base {
+namespace allocator {
+
+void SetupSubprocessAllocator() {
+#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+  size_t primary_length = 0;
+  getenv_s(&primary_length, NULL, 0, primary_name);
+
+  size_t secondary_length = 0;
+  char buffer[20];
+  getenv_s(&secondary_length, buffer, sizeof(buffer), secondary_name);
+  DCHECK_GT(sizeof(buffer), secondary_length);
+  buffer[sizeof(buffer) - 1] = '\0';
+
+  if (secondary_length || !primary_length) {
+    const char* secondary_value = secondary_length ? buffer : "TCMALLOC";
+    // Force renderer (or other subprocesses) to use secondary_value.
+    int ret_val = _putenv_s(primary_name, secondary_value);
+    DCHECK_EQ(0, ret_val);
+  }
+#endif  // ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
+}
+
+void* TCMallocDoMallocForTest(size_t size) {
+  return do_malloc(size);
+}
+
+void TCMallocDoFreeForTest(void* ptr) {
+  do_free(ptr);
+}
+
+size_t ExcludeSpaceForMarkForTest(size_t size) {
+  return ExcludeSpaceForMark(size);
+}
+
+}  // namespace allocator.
+}  // namespace base.
diff --git a/src/base/allocator/allocator_shim.h b/src/base/allocator/allocator_shim.h
new file mode 100644
index 0000000..e10fa8d
--- /dev/null
+++ b/src/base/allocator/allocator_shim.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ALLOCATOR_ALLOCATOR_SHIM_H_
+#define BASE_ALLOCATOR_ALLOCATOR_SHIM_H_
+
+namespace base {
+namespace allocator {
+
+// Resets the environment variable CHROME_ALLOCATOR to specify the choice to
+// be used by subprocesses.  Priority is given to the current value of
+// CHROME_ALLOCATOR_2 (if specified), then CHROME_ALLOCATOR (if specified), and
+// then a default value (typically set to TCMALLOC).
+void SetupSubprocessAllocator();
+
+// Expose some of tcmalloc functions for test.
+void* TCMallocDoMallocForTest(size_t size);
+void TCMallocDoFreeForTest(void* ptr);
+size_t ExcludeSpaceForMarkForTest(size_t size);
+
+}  // namespace allocator.
+}  // namespace base.
+
+#endif   // BASE_ALLOCATOR_ALLOCATOR_SHIM_H_
diff --git a/src/base/allocator/allocator_unittests.cc b/src/base/allocator/allocator_unittests.cc
new file mode 100644
index 0000000..3c455ba
--- /dev/null
+++ b/src/base/allocator/allocator_unittests.cc
@@ -0,0 +1,555 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <algorithm>   // for min()
+#include "base/atomicops.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Number of bits in a size_t.
+static const int kSizeBits = 8 * sizeof(size_t);
+// The maximum size of a size_t.
+static const size_t kMaxSize = ~static_cast<size_t>(0);
+// Maximum positive size of a size_t if it were signed.
+static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1);
+
+#if !defined(__LB_SHELL__) && !defined(OS_STARBOARD)
+// An allocation size which is not too big to be reasonable.
+static const size_t kNotTooBig = 100000;
+// An allocation size which is just too big.
+static const size_t kTooBig = ~static_cast<size_t>(0);
+#endif
+
+namespace {
+
+using std::min;
+
+// Fill a buffer of the specified size with a predetermined pattern
+static void Fill(unsigned char* buffer, int n) {
+  for (int i = 0; i < n; i++) {
+    buffer[i] = (i & 0xff);
+  }
+}
+
+// Check that the specified buffer has the predetermined pattern
+// generated by Fill()
+static bool Valid(unsigned char* buffer, int n) {
+  for (int i = 0; i < n; i++) {
+    if (buffer[i] != (i & 0xff)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// Check that a buffer is completely zeroed.
+static bool IsZeroed(unsigned char* buffer, int n) {
+  for (int i = 0; i < n; i++) {
+    if (buffer[i] != 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// Check alignment
+static void CheckAlignment(void* p, int align) {
+  EXPECT_EQ(0, reinterpret_cast<uintptr_t>(p) & (align-1));
+}
+
+// Return the next interesting size/delta to check.  Returns -1 if no more.
+static int NextSize(int size) {
+  if (size < 100)
+    return size+1;
+
+  if (size < 100000) {
+    // Find next power of two
+    int power = 1;
+    while (power < size)
+      power <<= 1;
+
+    // Yield (power-1, power, power+1)
+    if (size < power-1)
+      return power-1;
+
+    if (size == power-1)
+      return power;
+
+    assert(size == power);
+    return power+1;
+  } else {
+    return -1;
+  }
+}
+
+#if defined(__LB_SHELL__) || defined(OS_STARBOARD)
+#if defined(GG_ULONGLONG)
+// GG_ULONGLONG is already defined in base/port.h
+#undef GG_ULONGLONG
+#endif
+
+// namespace resolution for typedefs
+using base::subtle::AtomicWord;
+using base::subtle::Atomic32;
+#endif
+
+#define GG_ULONGLONG(x)  static_cast<uint64>(x)
+
+template <class AtomicType>
+static void TestAtomicIncrement() {
+  // For now, we just test single threaded execution
+
+  // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
+  // outside the expected address bounds.  This is in particular to
+  // test that some future change to the asm code doesn't cause the
+  // 32-bit NoBarrier_AtomicIncrement to do the wrong thing on 64-bit machines.
+  struct {
+    AtomicType prev_word;
+    AtomicType count;
+    AtomicType next_word;
+  } s;
+
+  AtomicType prev_word_value, next_word_value;
+  memset(&prev_word_value, 0xFF, sizeof(AtomicType));
+  memset(&next_word_value, 0xEE, sizeof(AtomicType));
+
+  s.prev_word = prev_word_value;
+  s.count = 0;
+  s.next_word = next_word_value;
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
+  EXPECT_EQ(s.count, 1);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
+  EXPECT_EQ(s.count, 3);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
+  EXPECT_EQ(s.count, 6);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
+  EXPECT_EQ(s.count, 3);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
+  EXPECT_EQ(s.count, 1);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
+  EXPECT_EQ(s.count, 0);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
+  EXPECT_EQ(s.count, -1);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
+  EXPECT_EQ(s.count, -5);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
+  EXPECT_EQ(s.count, 0);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+}
+
+
+#define NUM_BITS(T) (sizeof(T) * 8)
+
+
+template <class AtomicType>
+static void TestCompareAndSwap() {
+  AtomicType value = 0;
+  AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
+  EXPECT_EQ(1, value);
+  EXPECT_EQ(0, prev);
+
+  // Use test value that has non-zero bits in both halves, more for testing
+  // 64-bit implementation on 32-bit platforms.
+  const AtomicType k_test_val = (GG_ULONGLONG(1) <<
+                                 (NUM_BITS(AtomicType) - 2)) + 11;
+  value = k_test_val;
+  prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
+  EXPECT_EQ(k_test_val, value);
+  EXPECT_EQ(k_test_val, prev);
+
+  value = k_test_val;
+  prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
+  EXPECT_EQ(5, value);
+  EXPECT_EQ(k_test_val, prev);
+}
+
+
+template <class AtomicType>
+static void TestAtomicExchange() {
+  AtomicType value = 0;
+  AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
+  EXPECT_EQ(1, value);
+  EXPECT_EQ(0, new_value);
+
+  // Use test value that has non-zero bits in both halves, more for testing
+  // 64-bit implementation on 32-bit platforms.
+  const AtomicType k_test_val = (GG_ULONGLONG(1) <<
+                                 (NUM_BITS(AtomicType) - 2)) + 11;
+  value = k_test_val;
+  new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
+  EXPECT_EQ(k_test_val, value);
+  EXPECT_EQ(k_test_val, new_value);
+
+  value = k_test_val;
+  new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
+  EXPECT_EQ(5, value);
+  EXPECT_EQ(k_test_val, new_value);
+}
+
+
+template <class AtomicType>
+static void TestAtomicIncrementBounds() {
+  // Test increment at the half-width boundary of the atomic type.
+  // It is primarily for testing at the 32-bit boundary for 64-bit atomic type.
+  AtomicType test_val = GG_ULONGLONG(1) << (NUM_BITS(AtomicType) / 2);
+  AtomicType value = test_val - 1;
+  AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
+  EXPECT_EQ(test_val, value);
+  EXPECT_EQ(value, new_value);
+
+  base::subtle::NoBarrier_AtomicIncrement(&value, -1);
+  EXPECT_EQ(test_val - 1, value);
+}
+
+// This is a simple sanity check that values are correct. Not testing
+// atomicity
+template <class AtomicType>
+static void TestStore() {
+  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
+  const AtomicType kVal2 = static_cast<AtomicType>(-1);
+
+  AtomicType value;
+
+  base::subtle::NoBarrier_Store(&value, kVal1);
+  EXPECT_EQ(kVal1, value);
+  base::subtle::NoBarrier_Store(&value, kVal2);
+  EXPECT_EQ(kVal2, value);
+
+  base::subtle::Acquire_Store(&value, kVal1);
+  EXPECT_EQ(kVal1, value);
+  base::subtle::Acquire_Store(&value, kVal2);
+  EXPECT_EQ(kVal2, value);
+
+  base::subtle::Release_Store(&value, kVal1);
+  EXPECT_EQ(kVal1, value);
+  base::subtle::Release_Store(&value, kVal2);
+  EXPECT_EQ(kVal2, value);
+}
+
+// This is a simple sanity check that values are correct. Not testing
+// atomicity
+template <class AtomicType>
+static void TestLoad() {
+  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
+  const AtomicType kVal2 = static_cast<AtomicType>(-1);
+
+  AtomicType value;
+
+  value = kVal1;
+  EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
+  value = kVal2;
+  EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
+
+  value = kVal1;
+  EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
+  value = kVal2;
+  EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
+
+  value = kVal1;
+  EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
+  value = kVal2;
+  EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
+}
+
+template <class AtomicType>
+static void TestAtomicOps() {
+  TestCompareAndSwap<AtomicType>();
+  TestAtomicExchange<AtomicType>();
+  TestAtomicIncrementBounds<AtomicType>();
+  TestStore<AtomicType>();
+  TestLoad<AtomicType>();
+}
+
+static void TestCalloc(size_t n, size_t s, bool ok) {
+  char* p = reinterpret_cast<char*>(calloc(n, s));
+  if (!ok) {
+    EXPECT_EQ(NULL, p) << "calloc(n, s) should not succeed";
+  } else {
+  // TODO(__LB_SHELL__): This behavior is not defined by c++ standard.
+  // However it is possible that chromium expects it. We need to make sure
+  // these functions work the same way as expected by chromium when we override
+  // memory functions.
+    EXPECT_NE(reinterpret_cast<void*>(NULL), p) <<
+        "calloc(n, s) should succeed";
+    for (int i = 0; i < n*s; i++) {
+      EXPECT_EQ('\0', p[i]);
+    }
+    free(p);
+  }
+}
+
+#if !defined(__LB_SHELL__) && !defined(OS_STARBOARD)
+// Exceptions are disabled on lbshell and Starboard.
+
+// A global test counter for number of times the NewHandler is called.
+static int news_handled = 0;
+static void TestNewHandler() {
+  ++news_handled;
+  throw std::bad_alloc();
+}
+
+// Because we compile without exceptions, we expect these will not throw.
+static void TestOneNewWithoutExceptions(void* (*func)(size_t),
+                                        bool should_throw) {
+  // success test
+  try {
+    void* ptr = (*func)(kNotTooBig);
+    EXPECT_NE(reinterpret_cast<void*>(NULL), ptr) <<
+        "allocation should not have failed.";
+  } catch(...) {
+    EXPECT_EQ(0, 1) << "allocation threw unexpected exception.";
+  }
+
+  // failure test
+  try {
+    void* rv = (*func)(kTooBig);
+    EXPECT_EQ(NULL, rv);
+    EXPECT_FALSE(should_throw) << "allocation should have thrown.";
+  } catch(...) {
+    EXPECT_TRUE(should_throw) << "allocation threw unexpected exception.";
+  }
+}
+
+static void TestNothrowNew(void* (*func)(size_t)) {
+  news_handled = 0;
+
+  // test without new_handler:
+  std::new_handler saved_handler = std::set_new_handler(0);
+  TestOneNewWithoutExceptions(func, false);
+
+  // test with new_handler:
+  std::set_new_handler(TestNewHandler);
+  TestOneNewWithoutExceptions(func, true);
+  EXPECT_EQ(news_handled, 1) << "nothrow new_handler was not called.";
+  std::set_new_handler(saved_handler);
+}
+#endif
+}  // namespace
+
+//-----------------------------------------------------------------------------
+
+TEST(Atomics, AtomicIncrementWord) {
+  TestAtomicIncrement<AtomicWord>();
+}
+
+TEST(Atomics, AtomicIncrement32) {
+  TestAtomicIncrement<Atomic32>();
+}
+
+TEST(Atomics, AtomicOpsWord) {
+  TestAtomicIncrement<AtomicWord>();
+}
+
+TEST(Atomics, AtomicOps32) {
+  TestAtomicIncrement<Atomic32>();
+}
+
+TEST(Allocators, Malloc) {
+  // Try allocating data with a bunch of alignments and sizes
+  for (int size = 1; size < 1048576; size *= 2) {
+    unsigned char* ptr = reinterpret_cast<unsigned char*>(malloc(size));
+    CheckAlignment(ptr, 2);  // Should be 2 byte aligned
+    Fill(ptr, size);
+    EXPECT_TRUE(Valid(ptr, size));
+    free(ptr);
+  }
+}
+
+TEST(Allocators, Calloc) {
+  TestCalloc(0, 0, true);
+  TestCalloc(0, 1, true);
+  TestCalloc(1, 1, true);
+  TestCalloc(1<<10, 0, true);
+  TestCalloc(1<<20, 0, true);
+  TestCalloc(0, 1<<10, true);
+  TestCalloc(0, 1<<20, true);
+  TestCalloc(1<<20, 2, true);
+  TestCalloc(2, 1<<20, true);
+  TestCalloc(1000, 1000, true);
+
+  TestCalloc(kMaxSize, 2, false);
+  TestCalloc(2, kMaxSize, false);
+  TestCalloc(kMaxSize, kMaxSize, false);
+
+  TestCalloc(kMaxSignedSize, 3, false);
+  TestCalloc(3, kMaxSignedSize, false);
+  TestCalloc(kMaxSignedSize, kMaxSignedSize, false);
+}
+
+#if !defined(__LB_SHELL__) && !defined(OS_STARBOARD)
+// Exceptions are disabled on lbshell.
+TEST(Allocators, New) {
+  TestNothrowNew(&::operator new);
+  TestNothrowNew(&::operator new[]);
+}
+#endif
+
+#if !defined(__LB_SHELL__) && !defined(OS_STARBOARD)
+// The test assumes the memory space to be very empty
+// and doesn't work on lb_shell platforms.
+
+// This makes sure that reallocing a small number of bytes in either
+// direction doesn't cause us to allocate new memory.
+TEST(Allocators, Realloc1) {
+  int start_sizes[] = { 100, 1000, 10000, 100000 };
+  int deltas[] = { 1, -2, 4, -8, 16, -32, 64, -128 };
+
+  for (int s = 0; s < sizeof(start_sizes)/sizeof(*start_sizes); ++s) {
+    void* p = malloc(start_sizes[s]);
+    ASSERT_TRUE(p);
+    // The larger the start-size, the larger the non-reallocing delta.
+    for (int d = 0; d < s*2; ++d) {
+      void* new_p = realloc(p, start_sizes[s] + deltas[d]);
+      ASSERT_EQ(p, new_p);  // realloc should not allocate new memory
+    }
+    // Test again, but this time reallocing smaller first.
+    for (int d = 0; d < s*2; ++d) {
+      void* new_p = realloc(p, start_sizes[s] - deltas[d]);
+      ASSERT_EQ(p, new_p);  // realloc should not allocate new memory
+    }
+    free(p);
+  }
+}
+#endif
+
+TEST(Allocators, Realloc2) {
+  for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
+    for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) {
+      unsigned char* src = reinterpret_cast<unsigned char*>(malloc(src_size));
+      Fill(src, src_size);
+      unsigned char* dst =
+          reinterpret_cast<unsigned char*>(realloc(src, dst_size));
+      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
+      Fill(dst, dst_size);
+      EXPECT_TRUE(Valid(dst, dst_size));
+      if (dst != NULL) free(dst);
+    }
+  }
+
+  // Now make sure realloc works correctly even when we overflow the
+  // packed cache, so some entries are evicted from the cache.
+  // The cache has 2^12 entries, keyed by page number.
+  const int kNumEntries = 1 << 14;
+  int** p = reinterpret_cast<int**>(malloc(sizeof(*p) * kNumEntries));
+  int sum = 0;
+  for (int i = 0; i < kNumEntries; i++) {
+    // no page size is likely to be bigger than 8192?
+    p[i] = reinterpret_cast<int*>(malloc(8192));
+    p[i][1000] = i;              // use memory deep in the heart of p
+  }
+  for (int i = 0; i < kNumEntries; i++) {
+    p[i] = reinterpret_cast<int*>(realloc(p[i], 9000));
+  }
+  for (int i = 0; i < kNumEntries; i++) {
+    sum += p[i][1000];
+    free(p[i]);
+  }
+  EXPECT_EQ(kNumEntries/2 * (kNumEntries - 1), sum);  // assume kNE is even
+  free(p);
+}
+
+// TODO(__LB_SHELL__): This behavior is not defined by c++ standard.
+// However it is possible that chromium expects it. We need to make sure
+// these functions work the same way as expected by chromium when we override
+// memory functions.
+TEST(Allocators, ReallocZero) {
+  // Test that realloc to zero does not return NULL.
+  for (int size = 0; size >= 0; size = NextSize(size)) {
+    char* ptr = reinterpret_cast<char*>(malloc(size));
+    EXPECT_NE(static_cast<char*>(NULL), ptr);
+    ptr = reinterpret_cast<char*>(realloc(ptr, 0));
+    EXPECT_NE(static_cast<char*>(NULL), ptr);
+    if (ptr)
+      free(ptr);
+  }
+}
+
+#ifdef WIN32
+// Test recalloc
+TEST(Allocators, Recalloc) {
+  for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
+    for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) {
+      unsigned char* src =
+          reinterpret_cast<unsigned char*>(_recalloc(NULL, 1, src_size));
+      EXPECT_TRUE(IsZeroed(src, src_size));
+      Fill(src, src_size);
+      unsigned char* dst =
+          reinterpret_cast<unsigned char*>(_recalloc(src, 1, dst_size));
+      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
+      Fill(dst, dst_size);
+      EXPECT_TRUE(Valid(dst, dst_size));
+      if (dst != NULL)
+        free(dst);
+    }
+  }
+}
+
+// Test windows specific _aligned_malloc() and _aligned_free() methods.
+TEST(Allocators, AlignedMalloc) {
+  // Try allocating data with a bunch of alignments and sizes
+  static const int kTestAlignments[] = {8, 16, 256, 4096, 8192, 16384};
+  for (int size = 1; size > 0; size = NextSize(size)) {
+    for (int i = 0; i < ARRAYSIZE(kTestAlignments); ++i) {
+      unsigned char* ptr = static_cast<unsigned char*>(
+          _aligned_malloc(size, kTestAlignments[i]));
+      CheckAlignment(ptr, kTestAlignments[i]);
+      Fill(ptr, size);
+      EXPECT_TRUE(Valid(ptr, size));
+
+      // Make a second allocation of the same size and alignment to prevent
+      // allocators from passing this test by accident.  Per jar, tcmalloc
+      // provides allocations for new (never before seen) sizes out of a thread
+      // local heap of a given "size class."  Each time the test requests a new
+      // size, it will usually get the first element of a span, which is a
+      // 4K aligned allocation.
+      unsigned char* ptr2 = static_cast<unsigned char*>(
+          _aligned_malloc(size, kTestAlignments[i]));
+      CheckAlignment(ptr2, kTestAlignments[i]);
+      Fill(ptr2, size);
+      EXPECT_TRUE(Valid(ptr2, size));
+
+      // Should never happen, but sanity check just in case.
+      ASSERT_NE(ptr, ptr2);
+      _aligned_free(ptr);
+      _aligned_free(ptr2);
+    }
+  }
+}
+
+#endif
+
+#if !defined(__LB_SHELL__) && !defined(OS_STARBOARD)
+// main defined in run_all_unittests
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+#endif
diff --git a/src/base/allocator/debugallocation_shim.cc b/src/base/allocator/debugallocation_shim.cc
new file mode 100644
index 0000000..d1cf52a
--- /dev/null
+++ b/src/base/allocator/debugallocation_shim.cc
@@ -0,0 +1,9 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if defined(TCMALLOC_FOR_DEBUGALLOCATION)
+#include "third_party/tcmalloc/chromium/src/debugallocation.cc"
+#else
+#include "third_party/tcmalloc/chromium/src/tcmalloc.cc"
+#endif
diff --git a/src/base/allocator/generic_allocators.cc b/src/base/allocator/generic_allocators.cc
new file mode 100644
index 0000000..d4cf19e
--- /dev/null
+++ b/src/base/allocator/generic_allocators.cc
@@ -0,0 +1,168 @@
+// 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.
+
+// When possible, we implement allocator functions on top of the basic
+// low-level functions malloc() and free().  This way, including a new
+// allocator is as simple as providing just a small interface.
+//
+// As such, this file should not contain any allocator-specific code.
+
+// Implement a C++ style allocation, which always calls the new_handler
+// on failure.
+inline void* generic_cpp_alloc(size_t size, bool nothrow) {
+  void* ptr;
+  for (;;) {
+    ptr = malloc(size);
+    if (ptr)
+      return ptr;
+    if (!call_new_handler(nothrow))
+      break;
+  }
+  return ptr;
+}
+
+extern "C++" {
+
+void* __cdecl operator new(size_t size) {
+  return generic_cpp_alloc(size, false);
+}
+
+void operator delete(void* p) __THROW {
+  free(p);
+}
+
+void* operator new[](size_t size) {
+  return generic_cpp_alloc(size, false);
+}
+
+void operator delete[](void* p) __THROW {
+  free(p);
+}
+
+void* operator new(size_t size, const std::nothrow_t& nt) __THROW {
+  return generic_cpp_alloc(size, true);
+}
+
+void* operator new[](size_t size, const std::nothrow_t& nt) __THROW {
+  return generic_cpp_alloc(size, true);
+}
+
+// This function behaves similarly to MSVC's _set_new_mode.
+// If flag is 0 (default), calls to malloc will behave normally.
+// If flag is 1, calls to malloc will behave like calls to new,
+// and the std_new_handler will be invoked on failure.
+// Returns the previous mode.
+int _set_new_mode(int flag) __THROW {
+  int old_mode = new_mode;
+  new_mode = flag;
+  return old_mode;
+}
+
+}  // extern "C++"
+
+extern "C" {
+
+void* calloc(size_t n, size_t elem_size) __THROW {
+  // Overflow check
+  const size_t size = n * elem_size;
+  if (elem_size != 0 && size / elem_size != n) return NULL;
+
+  void* result = malloc(size);
+  if (result != NULL) {
+    memset(result, 0, size);
+  }
+  return result;
+}
+
+void cfree(void* p) __THROW {
+  free(p);
+}
+
+#ifdef WIN32
+
+void* _recalloc(void* p, size_t n, size_t elem_size) {
+  if (!p)
+    return calloc(n, elem_size);
+
+  // This API is a bit odd.
+  // Note: recalloc only guarantees zeroed memory when p is NULL.
+  //   Generally, calls to malloc() have padding.  So a request
+  //   to malloc N bytes actually malloc's N+x bytes.  Later, if
+  //   that buffer is passed to recalloc, we don't know what N
+  //   was anymore.  We only know what N+x is.  As such, there is
+  //   no way to know what to zero out.
+  const size_t size = n * elem_size;
+  if (elem_size != 0 && size / elem_size != n) return NULL;
+  return realloc(p, size);
+}
+
+void* _calloc_impl(size_t n, size_t size) {
+  return calloc(n, size);
+}
+
+#ifndef NDEBUG
+#undef malloc
+#undef free
+#undef calloc
+
+static int error_handler(int reportType) {
+  switch (reportType) {
+    case 0:  // _CRT_WARN
+      __debugbreak();
+      return 0;
+
+    case 1:  // _CRT_ERROR
+      __debugbreak();
+      return 0;
+
+    case 2:  // _CRT_ASSERT
+      __debugbreak();
+      return 0;
+  }
+  char* p = NULL;
+  *p = '\0';
+  return 0;
+}
+
+int _CrtDbgReport(int reportType,
+                  const char*,
+                  int, const char*,
+                  const char*,
+                  ...) {
+  return error_handler(reportType);
+}
+
+int _CrtDbgReportW(int reportType,
+                   const wchar_t*,
+                   int, const wchar_t*,
+                   const wchar_t*,
+                   ...) {
+  return error_handler(reportType);
+}
+
+int _CrtSetReportMode(int, int) {
+  return 0;
+}
+
+void* _malloc_dbg(size_t size, int , const char*, int) {
+  return malloc(size);
+}
+
+void* _realloc_dbg(void* ptr, size_t size, int, const char*, int) {
+  return realloc(ptr, size);
+}
+
+void _free_dbg(void* ptr, int) {
+  free(ptr);
+}
+
+void* _calloc_dbg(size_t n, size_t size, int, const char*, int) {
+  return calloc(n, size);
+}
+#endif  // NDEBUG
+
+#endif  // WIN32
+
+}  // extern C
+
diff --git a/src/base/allocator/prep_libc.py b/src/base/allocator/prep_libc.py
new file mode 100755
index 0000000..be7030f
--- /dev/null
+++ b/src/base/allocator/prep_libc.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This script takes libcmt.lib for VS2005/08/10 and removes the allocation
+# related functions from it.
+#
+# Usage: prep_libc.py <VCInstallDir> <OutputDir>
+#
+# VCInstallDir is the path where VC is installed, something like:
+#    C:\Program Files\Microsoft Visual Studio 8\VC\
+#
+# OutputDir is the directory where the modified libcmt file should be stored.
+
+import os
+import shutil
+import subprocess
+import sys
+
+def run(command, filter=None):
+  """Run |command|, removing any lines that match |filter|. The filter is
+  to remove the echoing of input filename that 'lib' does."""
+  popen = subprocess.Popen(
+      command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+  out, _ = popen.communicate()
+  for line in out.splitlines():
+    if filter and line.strip() != filter:
+      print line
+  return popen.returncode
+
+def main():
+  vs_install_dir = sys.argv[1]
+  outdir = sys.argv[2]
+  output_lib = os.path.join(outdir, 'libcmt.lib')
+  shutil.copyfile(os.path.join(vs_install_dir, 'libcmt.lib'), output_lib)
+  shutil.copyfile(os.path.join(vs_install_dir, 'libcmt.pdb'),
+                  os.path.join(outdir, 'libcmt.pdb'))
+  vspaths = [
+    'build\\intel\\mt_obj\\',
+    'f:\\dd\\vctools\\crt_bld\\SELF_X86\\crt\\src\\build\\INTEL\\mt_obj\\',
+    'F:\\dd\\vctools\\crt_bld\\SELF_X86\\crt\\src\\build\\INTEL\\mt_obj\\nativec\\\\',
+    'F:\\dd\\vctools\\crt_bld\\SELF_X86\\crt\\src\\build\\INTEL\\mt_obj\\nativecpp\\\\',
+  ]
+  objfiles = ['malloc', 'free', 'realloc', 'new', 'delete', 'new2', 'delete2',
+              'align', 'msize', 'heapinit', 'expand', 'heapchk', 'heapwalk',
+              'heapmin', 'sbheap', 'calloc', 'recalloc', 'calloc_impl',
+              'new_mode', 'newopnt']
+  for obj in objfiles:
+    for vspath in vspaths:
+      cmd = ('lib /nologo /ignore:4006,4014,4221 /remove:%s%s.obj %s' %
+             (vspath, obj, output_lib))
+      run(cmd, obj + '.obj')
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/src/base/allocator/tcmalloc_unittest.cc b/src/base/allocator/tcmalloc_unittest.cc
new file mode 100644
index 0000000..053a9d5
--- /dev/null
+++ b/src/base/allocator/tcmalloc_unittest.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include <stdio.h>
+#include "base/allocator/allocator_shim.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// TCMalloc header files
+#include "common.h"  // For TCMalloc constants like page size, etc.
+
+using base::allocator::TCMallocDoMallocForTest;
+using base::allocator::TCMallocDoFreeForTest;
+using base::allocator::ExcludeSpaceForMarkForTest;
+
+TEST(TCMallocFreeCheck, BadPointerInFirstPageOfTheLargeObject) {
+  char* p = reinterpret_cast<char*>(
+      TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1)));
+  for (int offset = 1; offset < kPageSize ; offset <<= 1) {
+    ASSERT_DEATH(TCMallocDoFreeForTest(p + offset),
+                 "Pointer is not pointing to the start of a span");
+  }
+}
+
+TEST(TCMallocFreeCheck, BadPageAlignedPointerInsideLargeObject) {
+  char* p = reinterpret_cast<char*>(
+      TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1)));
+
+  for (int offset = kPageSize; offset < kMaxSize; offset += kPageSize) {
+    // Only the first and last page of a span are in heap map. So for others
+    // tcmalloc will give a general error of invalid pointer.
+    ASSERT_DEATH(TCMallocDoFreeForTest(p + offset),
+                 "Attempt to free invalid pointer");
+  }
+  ASSERT_DEATH(TCMallocDoFreeForTest(p + kMaxSize),
+               "Pointer is not pointing to the start of a span");
+}
+
+TEST(TCMallocFreeCheck, DoubleFreeLargeObject) {
+  char* p = reinterpret_cast<char*>(
+      TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1)));
+  ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p),
+               "Object was not in-use");
+}
+
+
+#ifdef NDEBUG
+TEST(TCMallocFreeCheck, DoubleFreeSmallObject) {
+  for (size_t size = 1;
+       size <= ExcludeSpaceForMarkForTest(kMaxSize);
+       size <<= 1) {
+    char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size));
+    ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p),
+                 "Circular loop in list detected");
+  }
+}
+#else
+TEST(TCMallocFreeCheck, DoubleFreeSmallObject) {
+  size_t size = 1;
+
+  // When the object is small, tcmalloc validation can not distinguish normal
+  // memory corruption or double free, because there's not enough space in
+  // freed objects to keep the mark.
+  for (; size <= ExcludeSpaceForMarkForTest(kMinClassSize); size <<= 1) {
+    char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size));
+    ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p),
+                 "Memory corrupted");
+  }
+
+  for (; size <= ExcludeSpaceForMarkForTest(kMaxSize); size <<= 1) {
+    char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size));
+    ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p),
+                 "Attempt to double free");
+  }
+}
+#endif
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/base/allocator/type_profiler.cc b/src/base/allocator/type_profiler.cc
new file mode 100644
index 0000000..635fbcf
--- /dev/null
+++ b/src/base/allocator/type_profiler.cc
@@ -0,0 +1,63 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if defined(TYPE_PROFILING)
+
+#include "base/allocator/type_profiler.h"
+
+#include <assert.h>
+
+namespace {
+
+void* NopIntercept(void* ptr, size_t size, const std::type_info& type) {
+  return ptr;
+}
+
+base::type_profiler::InterceptFunction* g_new_intercept = NopIntercept;
+base::type_profiler::InterceptFunction* g_delete_intercept = NopIntercept;
+
+}
+
+void* __op_new_intercept__(void* ptr,
+                           size_t size,
+                           const std::type_info& type) {
+  return g_new_intercept(ptr, size, type);
+}
+
+void* __op_delete_intercept__(void* ptr,
+                              size_t size,
+                              const std::type_info& type) {
+  return g_delete_intercept(ptr, size, type);
+}
+
+namespace base {
+namespace type_profiler {
+
+// static
+void InterceptFunctions::SetFunctions(InterceptFunction* new_intercept,
+                                      InterceptFunction* delete_intercept) {
+  // Don't use DCHECK, as this file is injected into targets
+  // that do not and should not depend on base/base.gyp:base
+  assert(g_new_intercept == NopIntercept);
+  assert(g_delete_intercept == NopIntercept);
+
+  g_new_intercept = new_intercept;
+  g_delete_intercept = delete_intercept;
+}
+
+// static
+void InterceptFunctions::ResetFunctions() {
+  g_new_intercept = NopIntercept;
+  g_delete_intercept = NopIntercept;
+}
+
+// static
+bool InterceptFunctions::IsAvailable() {
+  return g_new_intercept != NopIntercept || g_delete_intercept != NopIntercept;
+}
+
+}  // namespace type_profiler
+}  // namespace base
+
+#endif  // defined(TYPE_PROFILING)
diff --git a/src/base/allocator/type_profiler.h b/src/base/allocator/type_profiler.h
new file mode 100644
index 0000000..86b5711
--- /dev/null
+++ b/src/base/allocator/type_profiler.h
@@ -0,0 +1,40 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ALLOCATOR_TYPE_PROFILER_H_
+#define BASE_ALLOCATOR_TYPE_PROFILER_H_
+
+#if defined(TYPE_PROFILING)
+
+#include <stddef.h>  // for size_t
+#include <typeinfo>  // for std::typeinfo
+
+namespace base {
+namespace type_profiler {
+
+typedef void* InterceptFunction(void*, size_t, const std::type_info&);
+
+class InterceptFunctions {
+ public:
+  // It must be called only once in a process while it is in single-thread.
+  // For now, ContentMainRunnerImpl::Initialize is the only supposed caller
+  // of this function except for single-threaded unit tests.
+  static void SetFunctions(InterceptFunction* new_intercept,
+                           InterceptFunction* delete_intercept);
+
+ private:
+  friend class TypeProfilerTest;
+
+  // These functions are not thread safe.
+  // They must be used only from single-threaded unit tests.
+  static void ResetFunctions();
+  static bool IsAvailable();
+};
+
+}  // namespace type_profiler
+}  // namespace base
+
+#endif  // defined(TYPE_PROFILING)
+
+#endif  // BASE_ALLOCATOR_TYPE_PROFILER_H_
diff --git a/src/base/allocator/type_profiler_control.cc b/src/base/allocator/type_profiler_control.cc
new file mode 100644
index 0000000..6be7984
--- /dev/null
+++ b/src/base/allocator/type_profiler_control.cc
@@ -0,0 +1,38 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/allocator/type_profiler_control.h"
+
+namespace base {
+namespace type_profiler {
+
+namespace {
+
+#if defined(TYPE_PROFILING)
+const bool kTypeProfilingEnabled = true;
+#else
+const bool kTypeProfilingEnabled = false;
+#endif
+
+bool g_enable_intercept = kTypeProfilingEnabled;
+
+}  // namespace
+
+// static
+void Controller::Stop() {
+  g_enable_intercept = false;
+}
+
+// static
+bool Controller::IsProfiling() {
+  return kTypeProfilingEnabled && g_enable_intercept;
+}
+
+// static
+void Controller::Restart() {
+  g_enable_intercept = kTypeProfilingEnabled;
+}
+
+}  // namespace type_profiler
+}  // namespace base
diff --git a/src/base/allocator/type_profiler_control.h b/src/base/allocator/type_profiler_control.h
new file mode 100644
index 0000000..17cf5b6
--- /dev/null
+++ b/src/base/allocator/type_profiler_control.h
@@ -0,0 +1,31 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ALLOCATOR_TYPE_PROFILER_CONTROL_H_
+#define BASE_ALLOCATOR_TYPE_PROFILER_CONTROL_H_
+
+#include "base/gtest_prod_util.h"
+
+namespace base {
+namespace type_profiler {
+
+class Controller {
+ public:
+  static void Stop();
+  static bool IsProfiling();
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(TypeProfilerTest,
+                           TestProfileNewWithoutProfiledDelete);
+
+  // It must be used only from allowed unit tests.  The following is only
+  // allowed for use in unit tests. Profiling should never be restarted in
+  // regular use.
+  static void Restart();
+};
+
+}  // namespace type_profiler
+}  // namespace base
+
+#endif  // BASE_ALLOCATOR_TYPE_PROFILER_CONTROL_H_
diff --git a/src/base/allocator/type_profiler_map_unittests.cc b/src/base/allocator/type_profiler_map_unittests.cc
new file mode 100644
index 0000000..ff74e11
--- /dev/null
+++ b/src/base/allocator/type_profiler_map_unittests.cc
@@ -0,0 +1,99 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a unittest set for type_profiler_map in third_party/tcmalloc.  It is
+// independent from other tests and executed manually like allocator_unittests
+// since type_profiler_map is a singleton (like TCMalloc's heap-profiler), and
+// it requires RTTI and different compiling/linking options from others.
+
+#if defined(TYPE_PROFILING)
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h"
+
+namespace base {
+namespace type_profiler {
+
+static const void* const g_const_null = static_cast<const void*>(NULL);
+
+TEST(TypeProfilerMapTest, NormalOperation) {
+  // Allocate an object just to get a valid address.
+  // This 'new' is not profiled by type_profiler.
+  scoped_ptr<int> dummy(new int(48));
+  const std::type_info* type;
+
+  type = LookupType(dummy.get());
+  EXPECT_EQ(g_const_null, type);
+
+  InsertType(dummy.get(), 12, typeid(int));
+  type = LookupType(dummy.get());
+  ASSERT_NE(g_const_null, type);
+  EXPECT_STREQ(typeid(int).name(), type->name());
+
+  EraseType(dummy.get());
+  type = LookupType(dummy.get());
+  EXPECT_EQ(g_const_null, type);
+}
+
+TEST(TypeProfilerMapTest, EraseWithoutInsert) {
+  scoped_ptr<int> dummy(new int(48));
+  const std::type_info* type;
+
+  for (int i = 0; i < 10; ++i) {
+    EraseType(dummy.get());
+    type = LookupType(dummy.get());
+    EXPECT_EQ(g_const_null, type);
+  }
+}
+
+TEST(TypeProfilerMapTest, InsertThenMultipleErase) {
+  scoped_ptr<int> dummy(new int(48));
+  const std::type_info* type;
+
+  InsertType(dummy.get(), 12, typeid(int));
+  type = LookupType(dummy.get());
+  ASSERT_NE(g_const_null, type);
+  EXPECT_STREQ(typeid(int).name(), type->name());
+
+  for (int i = 0; i < 10; ++i) {
+    EraseType(dummy.get());
+    type = LookupType(dummy.get());
+    EXPECT_EQ(g_const_null, type);
+  }
+}
+
+TEST(TypeProfilerMapTest, MultipleInsertWithoutErase) {
+  scoped_ptr<int> dummy(new int(48));
+  const std::type_info* type;
+
+  InsertType(dummy.get(), 12, typeid(int));
+  type = LookupType(dummy.get());
+  ASSERT_NE(g_const_null, type);
+  EXPECT_STREQ(typeid(int).name(), type->name());
+
+  InsertType(dummy.get(), 5, typeid(char));
+  type = LookupType(dummy.get());
+  ASSERT_NE(g_const_null, type);
+  EXPECT_STREQ(typeid(char).name(), type->name());
+
+  InsertType(dummy.get(), 129, typeid(long));
+  type = LookupType(dummy.get());
+  ASSERT_NE(g_const_null, type);
+  EXPECT_STREQ(typeid(long).name(), type->name());
+
+  EraseType(dummy.get());
+  type = LookupType(dummy.get());
+  EXPECT_EQ(g_const_null, type);
+}
+
+}  // namespace type_profiler
+}  // namespace base
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
+#endif  // defined(TYPE_PROFILING)
diff --git a/src/base/allocator/type_profiler_tcmalloc.cc b/src/base/allocator/type_profiler_tcmalloc.cc
new file mode 100644
index 0000000..e5e10e0
--- /dev/null
+++ b/src/base/allocator/type_profiler_tcmalloc.cc
@@ -0,0 +1,37 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if defined(TYPE_PROFILING)
+
+#include "base/allocator/type_profiler_tcmalloc.h"
+
+#include "base/allocator/type_profiler_control.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h"
+
+namespace base {
+namespace type_profiler {
+
+void* NewInterceptForTCMalloc(void* ptr,
+                              size_t size,
+                              const std::type_info& type) {
+  if (Controller::IsProfiling())
+    InsertType(ptr, size, type);
+
+  return ptr;
+}
+
+void* DeleteInterceptForTCMalloc(void* ptr,
+                                 size_t size,
+                                 const std::type_info& type) {
+  if (Controller::IsProfiling())
+    EraseType(ptr);
+
+  return ptr;
+}
+
+}  // namespace type_profiler
+}  // namespace base
+
+#endif  // defined(TYPE_PROFILING)
diff --git a/src/base/allocator/type_profiler_tcmalloc.h b/src/base/allocator/type_profiler_tcmalloc.h
new file mode 100644
index 0000000..ac55995
--- /dev/null
+++ b/src/base/allocator/type_profiler_tcmalloc.h
@@ -0,0 +1,29 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ALLOCATOR_TYPE_PROFILER_TCMALLOC_H_
+#define BASE_ALLOCATOR_TYPE_PROFILER_TCMALLOC_H_
+
+#if defined(TYPE_PROFILING)
+
+#include <cstddef>  // for size_t
+#include <typeinfo>  // for std::type_info
+
+namespace base {
+namespace type_profiler {
+
+void* NewInterceptForTCMalloc(void* ptr,
+                              size_t size,
+                              const std::type_info& type);
+
+void* DeleteInterceptForTCMalloc(void* ptr,
+                                 size_t size,
+                                 const std::type_info& type);
+
+}  // namespace type_profiler
+}  // namespace base
+
+#endif  // defined(TYPE_PROFILING)
+
+#endif  // BASE_ALLOCATOR_TYPE_PROFILER_TCMALLOC_H_
diff --git a/src/base/allocator/type_profiler_unittests.cc b/src/base/allocator/type_profiler_unittests.cc
new file mode 100644
index 0000000..16af86d
--- /dev/null
+++ b/src/base/allocator/type_profiler_unittests.cc
@@ -0,0 +1,189 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a unittest set for type_profiler.  It is independent from other
+// tests and executed manually like allocator_unittests since type_profiler_map
+// used in type_profiler is a singleton (like TCMalloc's heap-profiler), and
+// it requires RTTI and different compiling/linking options from others
+//
+// It tests that the profiler doesn't fail in suspicous cases.  For example,
+// 'new' is not profiled, but 'delete' for the created object is profiled.
+
+#if defined(TYPE_PROFILING)
+
+#include "base/allocator/type_profiler.h"
+#include "base/allocator/type_profiler_control.h"
+#include "base/allocator/type_profiler_tcmalloc.h"
+#include "base/basictypes.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h"
+
+namespace base {
+namespace type_profiler {
+
+class TypeProfilerTest : public testing::Test {
+ public:
+  TypeProfilerTest() {}
+
+  void SetInterceptFunctions() {
+    InterceptFunctions::SetFunctions(NewInterceptForTCMalloc,
+                                     DeleteInterceptForTCMalloc);
+  }
+
+  void ResetInterceptFunctions() {
+    InterceptFunctions::ResetFunctions();
+  }
+
+  void SetUp() {
+    SetInterceptFunctions();
+  }
+
+  void TearDown() {
+    ResetInterceptFunctions();
+  }
+
+ protected:
+  static const size_t kDummyArraySize;
+  static const void* const kConstNull;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TypeProfilerTest);
+};
+
+const size_t TypeProfilerTest::kDummyArraySize = 10;
+const void* const TypeProfilerTest::kConstNull = static_cast<const void*>(NULL);
+
+TEST_F(TypeProfilerTest, TestNormalProfiling) {
+  int* dummy = new int(48);
+  const std::type_info* type;
+
+  type = LookupType(dummy);
+  ASSERT_NE(kConstNull, type);
+  EXPECT_STREQ(typeid(int).name(), type->name());
+  delete dummy;
+
+  type = LookupType(dummy);
+  EXPECT_EQ(kConstNull, type);
+}
+
+TEST_F(TypeProfilerTest, TestNormalArrayProfiling) {
+  int* dummy = new int[kDummyArraySize];
+  const std::type_info* type;
+
+  type = LookupType(dummy);
+  ASSERT_NE(kConstNull, type);
+  // For an array, the profiler remembers its base type.
+  EXPECT_STREQ(typeid(int).name(), type->name());
+  delete[] dummy;
+
+  type = LookupType(dummy);
+  EXPECT_EQ(kConstNull, type);
+}
+
+TEST_F(TypeProfilerTest, TestRepeatedNewAndDelete) {
+  int *dummy[kDummyArraySize];
+  const std::type_info* type;
+  for (int i = 0; i < kDummyArraySize; ++i)
+    dummy[i] = new int(i);
+
+  for (int i = 0; i < kDummyArraySize; ++i) {
+    type = LookupType(dummy[i]);
+    ASSERT_NE(kConstNull, type);
+    EXPECT_STREQ(typeid(int).name(), type->name());
+  }
+
+  for (int i = 0; i < kDummyArraySize; ++i) {
+    delete dummy[i];
+    type = LookupType(dummy[i]);
+    ASSERT_EQ(kConstNull, type);
+  }
+}
+
+TEST_F(TypeProfilerTest, TestMultipleNewWithDroppingDelete) {
+  static const size_t large_size = 256 * 1024;
+
+  char* dummy_char = new char[large_size / sizeof(*dummy_char)];
+  const std::type_info* type;
+
+  type = LookupType(dummy_char);
+  ASSERT_NE(kConstNull, type);
+  EXPECT_STREQ(typeid(char).name(), type->name());
+
+  // Call "::operator delete" directly to drop __op_delete_intercept__.
+  ::operator delete[](dummy_char);
+
+  type = LookupType(dummy_char);
+  ASSERT_NE(kConstNull, type);
+  EXPECT_STREQ(typeid(char).name(), type->name());
+
+  // Allocates a little different size.
+  int* dummy_int = new int[large_size / sizeof(*dummy_int) - 1];
+
+  // We expect that tcmalloc returns the same address for these large (over 32k)
+  // allocation calls.  It usually happens, but maybe probablistic.
+  ASSERT_EQ(static_cast<void*>(dummy_char), static_cast<void*>(dummy_int)) <<
+      "two new (malloc) calls didn't return the same address; retry it.";
+
+  type = LookupType(dummy_int);
+  ASSERT_NE(kConstNull, type);
+  EXPECT_STREQ(typeid(int).name(), type->name());
+
+  delete[] dummy_int;
+
+  type = LookupType(dummy_int);
+  EXPECT_EQ(kConstNull, type);
+}
+
+TEST_F(TypeProfilerTest, TestProfileDeleteWithoutProfiledNew) {
+  // 'dummy' should be new'ed in this test before intercept functions are set.
+  ResetInterceptFunctions();
+
+  int* dummy = new int(48);
+  const std::type_info* type;
+
+  // Set intercept functions again after 'dummy' is new'ed.
+  SetInterceptFunctions();
+
+  delete dummy;
+
+  type = LookupType(dummy);
+  EXPECT_EQ(kConstNull, type);
+
+  ResetInterceptFunctions();
+}
+
+TEST_F(TypeProfilerTest, TestProfileNewWithoutProfiledDelete) {
+  int* dummy = new int(48);
+  const std::type_info* type;
+
+  EXPECT_TRUE(Controller::IsProfiling());
+
+  // Stop profiling before deleting 'dummy'.
+  Controller::Stop();
+  EXPECT_FALSE(Controller::IsProfiling());
+
+  delete dummy;
+
+  // NOTE: We accept that a profile entry remains when a profiled object is
+  // deleted after Controller::Stop().
+  type = LookupType(dummy);
+  ASSERT_NE(kConstNull, type);
+  EXPECT_STREQ(typeid(int).name(), type->name());
+
+  Controller::Restart();
+  EXPECT_TRUE(Controller::IsProfiling());
+
+  // Remove manually since 'dummy' is not removed from type_profiler_map.
+  EraseType(dummy);
+}
+
+}  // namespace type_profiler
+}  // namespace base
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
+#endif  // defined(TYPE_PROFILING)
diff --git a/src/base/allocator/unittest_utils.cc b/src/base/allocator/unittest_utils.cc
new file mode 100644
index 0000000..130ba15
--- /dev/null
+++ b/src/base/allocator/unittest_utils.cc
@@ -0,0 +1,18 @@
+// 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.
+
+// The unittests need a this in order to link up without pulling in tons
+// of other libraries
+
+#include <config.h>
+
+inline int snprintf(char* buffer, size_t count, const char* format, ...) {
+    int result;
+    va_list args;
+    va_start(args, format);
+    result = _vsnprintf(buffer, count, format, args);
+    va_end(args);
+    return result;
+}
+
diff --git a/src/base/allocator/win_allocator.cc b/src/base/allocator/win_allocator.cc
new file mode 100644
index 0000000..899b867
--- /dev/null
+++ b/src/base/allocator/win_allocator.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a simple allocator based on the windows heap.
+
+extern "C" {
+
+HANDLE win_heap;
+
+bool win_heap_init(bool use_lfh) {
+  win_heap = HeapCreate(0, 0, 0);
+  if (win_heap == NULL)
+    return false;
+
+  if (use_lfh) {
+    ULONG enable_lfh = 2;
+    HeapSetInformation(win_heap, HeapCompatibilityInformation,
+                       &enable_lfh, sizeof(enable_lfh));
+    // NOTE: Setting LFH may fail.  Vista already has it enabled.
+    //       And under the debugger, it won't use LFH.  So we
+    //       ignore any errors.
+  }
+
+  return true;
+}
+
+void* win_heap_malloc(size_t size) {
+  return HeapAlloc(win_heap, 0, size);
+}
+
+void win_heap_free(void* size) {
+  HeapFree(win_heap, 0, size);
+}
+
+void* win_heap_realloc(void* ptr, size_t size) {
+  if (!ptr)
+    return win_heap_malloc(size);
+  if (!size) {
+    win_heap_free(ptr);
+    return NULL;
+  }
+  return HeapReAlloc(win_heap, 0, ptr, size);
+}
+
+size_t win_heap_msize(void* ptr) {
+  return HeapSize(win_heap, 0, ptr);
+}
+
+void* win_heap_memalign(size_t alignment, size_t size) {
+  // Reserve enough space to ensure we can align and set aligned_ptr[-1] to the
+  // original allocation for use with win_heap_memalign_free() later.
+  size_t allocation_size = size + (alignment - 1) + sizeof(void*);
+
+  // Check for overflow.  Alignment and size are checked in allocator_shim.
+  DCHECK_LT(size, allocation_size);
+  DCHECK_LT(alignment, allocation_size);
+
+  void* ptr = win_heap_malloc(allocation_size);
+  char* aligned_ptr = static_cast<char*>(ptr) + sizeof(void*);
+  aligned_ptr +=
+      alignment - reinterpret_cast<uintptr_t>(aligned_ptr) & (alignment - 1);
+
+  reinterpret_cast<void**>(aligned_ptr)[-1] = ptr;
+  return aligned_ptr;
+}
+
+void win_heap_memalign_free(void* ptr) {
+  if (ptr)
+    win_heap_free(static_cast<void**>(ptr)[-1]);
+}
+
+}  // extern "C"
diff --git a/src/base/android/base_jni_registrar.cc b/src/base/android/base_jni_registrar.cc
new file mode 100644
index 0000000..2395d98
--- /dev/null
+++ b/src/base/android/base_jni_registrar.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/base_jni_registrar.h"
+
+#include "base/basictypes.h"
+#include "base/android/build_info.h"
+#include "base/android/cpu_features.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_registrar.h"
+#include "base/android/locale_utils.h"
+#include "base/android/path_service_android.h"
+#include "base/android/path_utils.h"
+#include "base/message_pump_android.h"
+#include "base/system_monitor/system_monitor_android.h"
+
+namespace base {
+namespace android {
+
+static RegistrationMethod kBaseRegisteredMethods[] = {
+  { "BuildInfo", base::android::BuildInfo::RegisterBindings },
+  { "CpuFeatures", base::android::RegisterCpuFeatures },
+  { "LocaleUtils", base::android::RegisterLocaleUtils },
+  { "PathService", base::android::RegisterPathService },
+  { "PathUtils", base::android::RegisterPathUtils },
+  { "SystemMessageHandler", base::MessagePumpForUI::RegisterBindings },
+  { "SystemMonitor", base::RegisterSystemMonitor },
+};
+
+bool RegisterJni(JNIEnv* env) {
+  return RegisterNativeMethods(env, kBaseRegisteredMethods,
+                               arraysize(kBaseRegisteredMethods));
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/base_jni_registrar.h b/src/base/android/base_jni_registrar.h
new file mode 100644
index 0000000..fdaf5f2
--- /dev/null
+++ b/src/base/android/base_jni_registrar.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_BASE_JNI_REGISTRAR_H_
+#define BASE_ANDROID_BASE_JNI_REGISTRAR_H_
+
+#include <jni.h>
+
+#include "base/base_export.h"
+
+namespace base {
+namespace android {
+
+// Register all JNI bindings necessary for base.
+BASE_EXPORT bool RegisterJni(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_BASE_JNI_REGISTRAR_H_
diff --git a/src/base/android/build_info.cc b/src/base/android/build_info.cc
new file mode 100644
index 0000000..cdde6a9
--- /dev/null
+++ b/src/base/android/build_info.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/build_info.h"
+
+#include <string>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "jni/BuildInfo_jni.h"
+
+namespace {
+
+// The caller takes ownership of the returned const char*.
+const char* StrDupJString(const base::android::JavaRef<jstring>& java_string) {
+  std::string str = ConvertJavaStringToUTF8(java_string);
+  return strdup(str.c_str());
+}
+
+}  // namespace
+
+namespace base {
+namespace android {
+
+struct BuildInfoSingletonTraits {
+  static BuildInfo* New() {
+    return new BuildInfo(AttachCurrentThread());
+  }
+
+  static void Delete(BuildInfo* x) {
+    // We're leaking this type, see kRegisterAtExit.
+    NOTREACHED();
+  }
+
+  static const bool kRegisterAtExit = false;
+  static const bool kAllowedToAccessOnNonjoinableThread = true;
+};
+
+BuildInfo::BuildInfo(JNIEnv* env)
+    : device_(StrDupJString(Java_BuildInfo_getDevice(env))),
+      model_(StrDupJString(Java_BuildInfo_getDeviceModel(env))),
+      brand_(StrDupJString(Java_BuildInfo_getBrand(env))),
+      android_build_id_(StrDupJString(Java_BuildInfo_getAndroidBuildId(env))),
+      android_build_fp_(StrDupJString(
+          Java_BuildInfo_getAndroidBuildFingerprint(env))),
+      package_version_code_(StrDupJString(Java_BuildInfo_getPackageVersionCode(
+          env, GetApplicationContext()))),
+      package_version_name_(StrDupJString(Java_BuildInfo_getPackageVersionName(
+          env, GetApplicationContext()))),
+      package_label_(StrDupJString(Java_BuildInfo_getPackageLabel(
+          env, GetApplicationContext()))),
+      package_name_(StrDupJString(Java_BuildInfo_getPackageName(
+          env, GetApplicationContext()))),
+      sdk_int_(Java_BuildInfo_getSdkInt(env)),
+      java_exception_info_(NULL) {
+}
+
+// static
+BuildInfo* BuildInfo::GetInstance() {
+  return Singleton<BuildInfo, BuildInfoSingletonTraits >::get();
+}
+
+void BuildInfo::set_java_exception_info(const std::string& info) {
+  DCHECK(!java_exception_info_) << "info should be set only once.";
+  java_exception_info_ = strndup(info.c_str(), 1024);
+}
+
+// static
+bool BuildInfo::RegisterBindings(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/build_info.h b/src/base/android/build_info.h
new file mode 100644
index 0000000..6273d3e
--- /dev/null
+++ b/src/base/android/build_info.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_BUILD_INFO_H_
+#define BASE_ANDROID_BUILD_INFO_H_
+
+#include <jni.h>
+
+#include <string>
+
+#include "base/memory/singleton.h"
+
+namespace base {
+namespace android {
+
+// BuildInfo is a singleton class that stores android build and device
+// information. It will be called from Android specific code and gets used
+// primarily in crash reporting.
+
+// It is also used to store the last java exception seen during JNI.
+// TODO(nileshagrawal): Find a better place to store this info.
+class BuildInfo {
+ public:
+
+  ~BuildInfo() {}
+
+  // Static factory method for getting the singleton BuildInfo instance.
+  // Note that ownership is not conferred on the caller and the BuildInfo in
+  // question isn't actually freed until shutdown. This is ok because there
+  // should only be one instance of BuildInfo ever created.
+  static BuildInfo* GetInstance();
+
+  // Const char* is used instead of std::strings because these values must be
+  // available even if the process is in a crash state. Sadly
+  // std::string.c_str() doesn't guarantee that memory won't be allocated when
+  // it is called.
+  const char* device() const {
+    return device_;
+  }
+
+  const char* model() const {
+    return model_;
+  }
+
+  const char* brand() const {
+    return brand_;
+  }
+
+  const char* android_build_id() const {
+    return android_build_id_;
+  }
+
+  const char* android_build_fp() const {
+    return android_build_fp_;
+  }
+
+  const char* package_version_code() const {
+    return package_version_code_;
+  }
+
+  const char* package_version_name() const {
+    return package_version_name_;
+  }
+
+  const char* package_label() const {
+    return package_label_;
+  }
+
+  const char* package_name() const {
+    return package_name_;
+  }
+
+  int sdk_int() const {
+    return sdk_int_;
+  }
+
+  const char* java_exception_info() const {
+    return java_exception_info_;
+  }
+
+  void set_java_exception_info(const std::string& info);
+
+  static bool RegisterBindings(JNIEnv* env);
+
+ private:
+  friend struct BuildInfoSingletonTraits;
+
+  explicit BuildInfo(JNIEnv* env);
+
+  // Const char* is used instead of std::strings because these values must be
+  // available even if the process is in a crash state. Sadly
+  // std::string.c_str() doesn't guarantee that memory won't be allocated when
+  // it is called.
+  const char* const device_;
+  const char* const model_;
+  const char* const brand_;
+  const char* const android_build_id_;
+  const char* const android_build_fp_;
+  const char* const package_version_code_;
+  const char* const package_version_name_;
+  const char* const package_label_;
+  const char* const package_name_;
+  const int sdk_int_;
+  // This is set via set_java_exception_info, not at constructor time.
+  const char* java_exception_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(BuildInfo);
+};
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_BUILD_INFO_H_
diff --git a/src/base/android/cpu_features.cc b/src/base/android/cpu_features.cc
new file mode 100644
index 0000000..6a18695
--- /dev/null
+++ b/src/base/android/cpu_features.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cpu-features.h>
+
+#include "base/android/jni_android.h"
+#include "jni/CpuFeatures_jni.h"
+
+namespace base {
+namespace android {
+
+jint GetCoreCount(JNIEnv*, jclass) {
+  return android_getCpuCount();
+}
+
+jlong GetCpuFeatures(JNIEnv*, jclass) {
+  return android_getCpuFeatures();
+}
+
+bool RegisterCpuFeatures(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/cpu_features.h b/src/base/android/cpu_features.h
new file mode 100644
index 0000000..0a27822
--- /dev/null
+++ b/src/base/android/cpu_features.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_CPU_FEATURES_H_
+#define BASE_ANDROID_CPU_FEATURES_H_
+
+#include <jni.h>
+
+namespace base {
+namespace android {
+
+bool RegisterCpuFeatures(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_CPU_FEATURES_H_
diff --git a/src/base/android/java/src/org/chromium/base/AccessedByNative.java b/src/base/android/java/src/org/chromium/base/AccessedByNative.java
new file mode 100644
index 0000000..8248cc6
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/AccessedByNative.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *  @AccessedByNative is used to ensure proguard will keep this field, since it's
+ *  only accessed by native.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AccessedByNative {
+    public String value() default "";
+}
diff --git a/src/base/android/java/src/org/chromium/base/ActivityStatus.java b/src/base/android/java/src/org/chromium/base/ActivityStatus.java
new file mode 100644
index 0000000..e728870
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/ActivityStatus.java
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.app.Activity;
+import android.os.Looper;
+
+import java.util.ArrayList;
+
+/**
+ * Provides information about the parent activity's status.
+ */
+public class ActivityStatus {
+
+    // Constants matching activity states reported to StateListener.onStateChange
+    public static final int CREATED = 1;
+    public static final int STARTED = 2;
+    public static final int RESUMED = 3;
+    public static final int PAUSED = 4;
+    public static final int STOPPED = 5;
+    public static final int DESTROYED = 6;
+
+    // Current main activity, or null if none.
+    private static Activity sActivity;
+
+    // Current main activity's state. This can be set even if sActivity is null, to simplify unit
+    // testing.
+    private static int sActivityState;
+
+    private static final ArrayList<StateListener> sStateListeners = new ArrayList<StateListener>();
+
+    // Use this interface to listen to all state changes.
+    public interface StateListener {
+        /**
+         * Called when the activity's state changes.
+         * @param newState New activity state.
+         */
+        public void onActivityStateChange(int newState);
+    }
+
+    private ActivityStatus() {}
+
+    /**
+     * Must be called by the main activity when it changes state.
+     * @param activity Current activity.
+     * @param newState New state value.
+     */
+    public static void onStateChange(Activity activity, int newState) {
+        if (newState == CREATED) {
+            sActivity = activity;
+        }
+        sActivityState = newState;
+        for (StateListener listener : sStateListeners) {
+            listener.onActivityStateChange(newState);
+        }
+        if (newState == DESTROYED) {
+            sActivity = null;
+        }
+    }
+
+    /**
+     * Indicates that the parent activity is currently paused.
+     */
+    public static boolean isPaused() {
+        return sActivityState == PAUSED;
+    }
+
+    /**
+     * Returns the current main application activity.
+     */
+    public static Activity getActivity() {
+        return sActivity;
+    }
+
+    /**
+     * Returns the current main application activity's state.
+     */
+    public static int getState() {
+        return sActivityState;
+    }
+
+    /**
+     * Registers the given listener to receive activity state changes.
+     * @param listener Listener to receive state changes.
+     */
+    public static void registerStateListener(StateListener listener) {
+        sStateListeners.add(listener);
+    }
+
+    /**
+     * Unregisters the given listener from receiving activity state changes.
+     * @param listener Listener that doesn't want to receive state changes.
+     */
+    public static void unregisterStateListener(StateListener listener) {
+        sStateListeners.remove(listener);
+    }
+}
diff --git a/src/base/android/java/src/org/chromium/base/BuildInfo.java b/src/base/android/java/src/org/chromium/base/BuildInfo.java
new file mode 100644
index 0000000..2314051
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/BuildInfo.java
@@ -0,0 +1,114 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build;
+import android.util.Log;
+
+import org.chromium.base.CalledByNative;
+
+/**
+ * BuildInfo is a utility class providing easy access to {@link PackageInfo}
+ * information. This is primarly of use for accessesing package information
+ * from native code.
+ */
+public class BuildInfo {
+    private static final String TAG = "BuildInfo";
+    private static final int MAX_FINGERPRINT_LENGTH = 128;
+
+    /**
+     * BuildInfo is a static utility class and therefore shouldn't be
+     * instantiated.
+     */
+    private BuildInfo() {
+    }
+
+    @CalledByNative
+    public static String getDevice() {
+        return Build.DEVICE;
+    }
+
+    @CalledByNative
+    public static String getBrand() {
+        return Build.BRAND;
+    }
+
+    @CalledByNative
+    public static String getAndroidBuildId() {
+        return Build.ID;
+    }
+
+    /**
+     * @return The build fingerprint for the current Android install.  The value is truncated to a
+     *         128 characters as this is used for crash and UMA reporting, which should avoid huge
+     *         strings.
+     */
+    @CalledByNative
+    public static String getAndroidBuildFingerprint() {
+        return Build.FINGERPRINT.substring(
+                0, Math.min(Build.FINGERPRINT.length(), MAX_FINGERPRINT_LENGTH));
+    }
+
+    @CalledByNative
+    public static String getDeviceModel() {
+        return Build.MODEL;
+    }
+
+    @CalledByNative
+    public static String getPackageVersionCode(Context context) {
+        String msg = "versionCode not available.";
+        try {
+            PackageManager pm = context.getPackageManager();
+            PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
+            msg = "" + pi.versionCode;
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, msg);
+        }
+        return msg;
+
+    }
+
+    @CalledByNative
+    public static String getPackageVersionName(Context context) {
+        String msg = "versionName not available";
+        try {
+            PackageManager pm = context.getPackageManager();
+            PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
+            msg = pi.versionName;
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, msg);
+        }
+        return msg;
+    }
+
+    @CalledByNative
+    public static String getPackageLabel(Context context) {
+        try {
+            PackageManager packageManager = context.getPackageManager();
+            ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(),
+                    PackageManager.GET_META_DATA);
+            CharSequence label = packageManager.getApplicationLabel(appInfo);
+            return  label != null ? label.toString() : "";
+        } catch (NameNotFoundException e) {
+            return "";
+        }
+    }
+
+    @CalledByNative
+    public static String getPackageName(Context context) {
+        String packageName = context != null ? context.getPackageName() : null;
+        return packageName != null ? packageName : "";
+    }
+
+    @CalledByNative
+    public static int getSdkInt() {
+        return Build.VERSION.SDK_INT;
+    }
+}
diff --git a/src/base/android/java/src/org/chromium/base/CalledByNative.java b/src/base/android/java/src/org/chromium/base/CalledByNative.java
new file mode 100644
index 0000000..8d3dcad
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/CalledByNative.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @CalledByNative is used by the JNI generator to create the necessary JNI
+ * bindings and expose this method to native code.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CalledByNative {
+    /*
+     *  If present, tells which inner class the method belongs to.
+     */
+    public String value() default "";
+}
diff --git a/src/base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java b/src/base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java
new file mode 100644
index 0000000..cc264a2
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *  @CalledByNativeUnchecked is used to generate JNI bindings that do not check for exceptions.
+ *  It only makes sense to use this annotation on methods that declare a throws... spec.
+ *  However, note that the exception received native side maybe an 'unchecked' (RuntimeExpception)
+ *  such as NullPointerException, so the native code should differentiate these cases.
+ *  Usage of this should be very rare; where possible handle exceptions in the Java side and use a
+ *  return value to indicate success / failure.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CalledByNativeUnchecked {
+    /*
+     *  If present, tells which inner class the method belongs to.
+     */
+    public String value() default "";
+}
diff --git a/src/base/android/java/src/org/chromium/base/ChromiumActivity.java b/src/base/android/java/src/org/chromium/base/ChromiumActivity.java
new file mode 100644
index 0000000..65f5ce9
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/ChromiumActivity.java
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+// All Chromium main activities should extend this class. This allows various sub-systems to
+// properly react to activity state changes.
+public class ChromiumActivity extends Activity {
+
+  @Override
+  protected void onCreate(Bundle savedInstance) {
+    super.onCreate(savedInstance);
+    ActivityStatus.onStateChange(this, ActivityStatus.CREATED);
+  }
+
+  @Override
+  protected void onStart() {
+    super.onStart();
+    ActivityStatus.onStateChange(this, ActivityStatus.STARTED);
+  }
+
+  @Override
+  protected void onResume() {
+    super.onResume();
+    ActivityStatus.onStateChange(this, ActivityStatus.RESUMED);
+  }
+
+  @Override
+  protected void onPause() {
+    ActivityStatus.onStateChange(this, ActivityStatus.PAUSED);
+    super.onPause();
+  }
+
+  @Override
+  protected void onStop() {
+    ActivityStatus.onStateChange(this, ActivityStatus.STOPPED);
+    super.onStop();
+  }
+
+  @Override
+  protected void onDestroy() {
+    ActivityStatus.onStateChange(this, ActivityStatus.DESTROYED);
+    super.onDestroy();
+  }
+}
diff --git a/src/base/android/java/src/org/chromium/base/CpuFeatures.java b/src/base/android/java/src/org/chromium/base/CpuFeatures.java
new file mode 100644
index 0000000..f298fb1
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/CpuFeatures.java
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+// The only purpose of this class is to allow sending CPU properties
+// from the browser process to sandboxed renderer processes. This is
+// needed because sandboxed processes cannot, on ARM, query the kernel
+// about the CPU's properties by parsing /proc, so this operation must
+// be performed in the browser process, and the result passed to
+// renderer ones.
+//
+// For more context, see http://crbug.com/164154
+//
+// Technically, this is a wrapper around the native NDK cpufeatures
+// library. The exact CPU features bits are never used in Java so
+// there is no point in duplicating their definitions here.
+//
+@JNINamespace("base::android")
+public abstract class CpuFeatures {
+    /**
+     * Return the number of CPU Cores on the device.
+     */
+    public static int getCount() {
+        return nativeGetCoreCount();
+    }
+
+    /**
+     * Return the CPU feature mask.
+     * This is a 64-bit integer that corresponds to the CPU's features.
+     * The value comes directly from android_getCpuFeatures().
+     */
+     public static long getMask() {
+        return nativeGetCpuFeatures();
+     }
+
+    private static native int nativeGetCoreCount();
+    private static native long nativeGetCpuFeatures();
+}
diff --git a/src/base/android/java/src/org/chromium/base/JNINamespace.java b/src/base/android/java/src/org/chromium/base/JNINamespace.java
new file mode 100644
index 0000000..cfffc91
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/JNINamespace.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @JNINamespace is used by the JNI generator to create the necessary JNI
+ * bindings and expose this method to native code using the specified namespace.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JNINamespace {
+    public String value();
+}
diff --git a/src/base/android/java/src/org/chromium/base/LocaleUtils.java b/src/base/android/java/src/org/chromium/base/LocaleUtils.java
new file mode 100644
index 0000000..6bca1f7
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import java.util.Locale;
+
+/**
+ * This class provides the locale related methods for the native library.
+ */
+class LocaleUtils {
+
+    private LocaleUtils() { /* cannot be instantiated */ }
+
+    /**
+     * @return the default locale.
+     */
+    @CalledByNative
+    public static String getDefaultLocale() {
+        Locale locale = Locale.getDefault();
+        String language = locale.getLanguage();
+        String country = locale.getCountry();
+        return country.isEmpty() ? language : language + "-" + country;
+    }
+}
diff --git a/src/base/android/java/src/org/chromium/base/NativeClassQualifiedName.java b/src/base/android/java/src/org/chromium/base/NativeClassQualifiedName.java
new file mode 100644
index 0000000..309169b
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/NativeClassQualifiedName.java
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @NativeClassQualifiedName is used by the JNI generator to create the necessary JNI
+ * bindings to call into the specified native class name.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NativeClassQualifiedName {
+    /*
+     * Tells which native class the method is going to be bound to.
+     * The first parameter of the annotated method must be an int nativePtr pointing to
+     * an instance of this class.
+     */
+    public String value();
+}
diff --git a/src/base/android/java/src/org/chromium/base/PathService.java b/src/base/android/java/src/org/chromium/base/PathService.java
new file mode 100644
index 0000000..dfda736
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/PathService.java
@@ -0,0 +1,24 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+/**
+ * This class provides java side access to the native PathService.
+ */
+@JNINamespace("base::android")
+public abstract class PathService {
+
+    // Must match the value of DIR_MODULE in base/base_paths.h!
+    public static final int DIR_MODULE = 3;
+
+    // Prevent instantiation.
+    private PathService() {}
+
+    public static void override(int what, String path) {
+        nativeOverride(what, path);
+    }
+
+    private static native void nativeOverride(int what, String path);
+}
diff --git a/src/base/android/java/src/org/chromium/base/PathUtils.java b/src/base/android/java/src/org/chromium/base/PathUtils.java
new file mode 100644
index 0000000..c3503a4
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/PathUtils.java
@@ -0,0 +1,85 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.os.Environment;
+
+/**
+ * This class provides the path related methods for the native library.
+ */
+public abstract class PathUtils {
+
+    private static String sDataDirectorySuffix;
+
+    // Prevent instantiation.
+    private PathUtils() {}
+
+    /**
+     * Sets the suffix that should be used for the directory where private data is to be stored
+     * by the application.
+     * @param suffix The private data directory suffix.
+     * @see Context#getDir(String, int)
+     */
+    public static void setPrivateDataDirectorySuffix(String suffix) {
+        sDataDirectorySuffix = suffix;
+    }
+
+    /**
+     * @return the private directory that is used to store application data.
+     */
+    @CalledByNative
+    public static String getDataDirectory(Context appContext) {
+        if (sDataDirectorySuffix == null) {
+            throw new IllegalStateException(
+                    "setDataDirectorySuffix must be called before getDataDirectory");
+        }
+        return appContext.getDir(sDataDirectorySuffix, Context.MODE_PRIVATE).getPath();
+    }
+
+    /**
+     * @return the cache directory.
+     */
+    @SuppressWarnings("unused")
+    @CalledByNative
+    private static String getCacheDirectory(Context appContext) {
+        return appContext.getCacheDir().getPath();
+    }
+
+    /**
+     * @return the public downloads directory.
+     */
+    @SuppressWarnings("unused")
+    @CalledByNative
+    private static String getDownloadsDirectory(Context appContext) {
+        return Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_DOWNLOADS).getPath();
+    }
+
+    /**
+     * @return the path to native libraries.
+     */
+    @SuppressWarnings("unused")
+    @CalledByNative
+    private static String getNativeLibraryDirectory(Context appContext) {
+        ApplicationInfo ai = appContext.getApplicationInfo();
+        if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ||
+            (ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+            return ai.nativeLibraryDir;
+        }
+
+        return "/system/lib/";
+    }
+
+    /**
+     * @return the external storage directory.
+     */
+    @SuppressWarnings("unused")
+    @CalledByNative
+    public static String getExternalStorageDirectory() {
+        return Environment.getExternalStorageDirectory().getAbsolutePath();
+    }
+}
diff --git a/src/base/android/java/src/org/chromium/base/PowerStatusReceiver.java b/src/base/android/java/src/org/chromium/base/PowerStatusReceiver.java
new file mode 100644
index 0000000..89594b8
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/PowerStatusReceiver.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+
+/**
+ * A BroadcastReceiver that listens to changes in power status and notifies
+ * SystemMonitor.
+ * It's instantiated by the framework via the application intent-filter
+ * declared in its manifest.
+ */
+public class PowerStatusReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        SystemMonitor.onBatteryChargingChanged(intent);
+    }
+}
diff --git a/src/base/android/java/src/org/chromium/base/SystemMessageHandler.java b/src/base/android/java/src/org/chromium/base/SystemMessageHandler.java
new file mode 100644
index 0000000..f7bb19f
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/SystemMessageHandler.java
@@ -0,0 +1,93 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+class SystemMessageHandler extends Handler {
+
+    private static final int TIMER_MESSAGE = 1;
+    private static final int DELAYED_TIMER_MESSAGE = 2;
+
+    // Native class pointer set by the constructor of the SharedClient native class.
+    private int mMessagePumpDelegateNative = 0;
+
+    // Used to ensure we have at most one TIMER_MESSAGE pending at once.
+    private AtomicBoolean mTimerFired = new AtomicBoolean(true);
+
+    // Used to insert TIMER_MESSAGE on the front of the system message queue during startup only.
+    // This is a wee hack, to give a priority boost to native tasks during startup as they tend to
+    // be on the critical path. (After startup, handling the UI with minimum latency is more
+    // important).
+    private boolean mStartupComplete = false;
+    private final long mStartupCompleteTime = System.currentTimeMillis() + 2000;
+    private final boolean startupComplete() {
+        if (!mStartupComplete && System.currentTimeMillis() > mStartupCompleteTime) {
+            mStartupComplete = true;
+        }
+        return mStartupComplete;
+    }
+
+    private SystemMessageHandler(int messagePumpDelegateNative) {
+        mMessagePumpDelegateNative = messagePumpDelegateNative;
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        if (msg.what == TIMER_MESSAGE) {
+            mTimerFired.set(true);
+        }
+        while (nativeDoRunLoopOnce(mMessagePumpDelegateNative)) {
+            if (startupComplete()) {
+                setTimer();
+                break;
+            }
+        }
+    }
+
+    @CalledByNative
+    private void setTimer() {
+        if (!mTimerFired.getAndSet(false)) {
+            // mTimerFired was already false.
+            return;
+        }
+        if (startupComplete()) {
+            sendEmptyMessage(TIMER_MESSAGE);
+        } else {
+            sendMessageAtFrontOfQueue(obtainMessage(TIMER_MESSAGE));
+        }
+    }
+
+    // If millis <=0, it'll send a TIMER_MESSAGE instead of
+    // a DELAYED_TIMER_MESSAGE.
+    @SuppressWarnings("unused")
+    @CalledByNative
+    private void setDelayedTimer(long millis) {
+        if (millis <= 0) {
+            setTimer();
+        } else {
+            removeMessages(DELAYED_TIMER_MESSAGE);
+            sendEmptyMessageDelayed(DELAYED_TIMER_MESSAGE, millis);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    @CalledByNative
+    private void removeTimer() {
+        removeMessages(TIMER_MESSAGE);
+        removeMessages(DELAYED_TIMER_MESSAGE);
+    }
+
+    @CalledByNative
+    private static SystemMessageHandler create(int messagePumpDelegateNative) {
+        return new SystemMessageHandler(messagePumpDelegateNative);
+    }
+
+    private native boolean nativeDoRunLoopOnce(int messagePumpDelegateNative);
+}
diff --git a/src/base/android/java/src/org/chromium/base/SystemMonitor.java b/src/base/android/java/src/org/chromium/base/SystemMonitor.java
new file mode 100644
index 0000000..30f61a6
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/SystemMonitor.java
@@ -0,0 +1,90 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.Looper;
+
+
+/**
+ * Integrates native SystemMonitor with the java side.
+ */
+@JNINamespace("base::android")
+public class SystemMonitor implements ActivityStatus.StateListener {
+    private static final long SUSPEND_DELAY_MS = 1 * 60 * 1000;  // 1 minute.
+    private static SystemMonitor sInstance;
+
+    private boolean mIsBatteryPower;
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    // Asynchronous task used to fire the "paused" event to the native side 1 minute after the main
+    // activity transitioned to the "paused" state. This event is not sent immediately because it
+    // would be too aggressive. An Android activity can be in the "paused" state quite often. This
+    // can happen when a dialog window shows up for instance.
+    private static final Runnable sSuspendTask = new Runnable() {
+            @Override
+            public void run() {
+                nativeOnMainActivitySuspended();
+            }
+        };
+
+    public static void createForTests(Context context) {
+        // Applications will create this once the JNI side has been fully wired up both sides. For
+        // tests, we just need native -> java, that is, we don't need to notify java -> native on
+        // creation.
+        sInstance = new SystemMonitor();
+    }
+
+    public static void create(Context context) {
+        if (sInstance == null) {
+            sInstance = new SystemMonitor();
+            ActivityStatus.registerStateListener(sInstance);
+            IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+            Intent batteryStatusIntent = context.registerReceiver(null, ifilter);
+            onBatteryChargingChanged(batteryStatusIntent);
+        }
+    }
+
+    private SystemMonitor() {
+    }
+
+    public static void onBatteryChargingChanged(Intent intent) {
+        if (sInstance == null) {
+            // We may be called by the framework intent-filter before being fully initialized. This
+            // is not a problem, since our constructor will check for the state later on.
+            return;
+        }
+        int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+        // If we're not plugged, assume we're running on battery power.
+        sInstance.mIsBatteryPower = chargePlug != BatteryManager.BATTERY_PLUGGED_USB &&
+                                    chargePlug != BatteryManager.BATTERY_PLUGGED_AC;
+        nativeOnBatteryChargingChanged();
+    }
+
+    @Override
+    public void onActivityStateChange(int newState) {
+        if (newState == ActivityStatus.RESUMED) {
+            // Remove the callback from the message loop in case it hasn't been executed yet.
+            mHandler.removeCallbacks(sSuspendTask);
+            nativeOnMainActivityResumed();
+        } else if (newState == ActivityStatus.PAUSED) {
+            mHandler.postDelayed(sSuspendTask, SUSPEND_DELAY_MS);
+        }
+    }
+
+    @CalledByNative
+    private static boolean isBatteryPower() {
+        return sInstance.mIsBatteryPower;
+    }
+
+    private static native void nativeOnBatteryChargingChanged();
+    private static native void nativeOnMainActivitySuspended();
+    private static native void nativeOnMainActivityResumed();
+}
diff --git a/src/base/android/java/src/org/chromium/base/ThreadUtils.java b/src/base/android/java/src/org/chromium/base/ThreadUtils.java
new file mode 100644
index 0000000..70232c4
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -0,0 +1,152 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
+/**
+ * Helper methods to deal with threading related tasks.
+ */
+public class ThreadUtils {
+
+    /**
+     * Run the supplied Runnable on the main thread. The method will block until
+     * the Runnable completes.
+     *
+     * @param r The Runnable to run.
+     */
+    public static void runOnUiThreadBlocking(final Runnable r) {
+        if (runningOnUiThread()) {
+            r.run();
+        } else {
+            FutureTask<Void> task = new FutureTask<Void>(r, null);
+            postOnUiThread(task);
+            try {
+                task.get();
+            } catch (Exception e) {
+                throw new RuntimeException("Exception occured while waiting for runnable", e);
+            }
+        }
+    }
+
+    /**
+     * Run the supplied Callable on the main thread, wrapping any exceptions in
+     * a RuntimeException. The method will block until the Callable completes.
+     *
+     * @param c The Callable to run
+     * @return The result of the callable
+     */
+    public static <T> T runOnUiThreadBlockingNoException(Callable<T> c) {
+        try {
+            return runOnUiThreadBlocking(c);
+        } catch (ExecutionException e) {
+            throw new RuntimeException("Error occured waiting for callable", e);
+        }
+    }
+
+    /**
+     * Run the supplied Callable on the main thread, The method will block until
+     * the Callable completes.
+     *
+     * @param c The Callable to run
+     * @return The result of the callable
+     * @throws ExecutionException c's exception
+     */
+    public static <T> T runOnUiThreadBlocking(Callable<T> c) throws ExecutionException {
+        FutureTask<T> task = new FutureTask<T>(c);
+        runOnUiThread(task);
+        try {
+            return task.get();
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for callable", e);
+        }
+    }
+
+    /**
+     * Run the supplied FutureTask on the main thread. The method will block
+     * only if the current thread is the main thread.
+     *
+     * @param task The FutureTask to run
+     * @return The queried task (to aid inline construction)
+     */
+    public static <T> FutureTask<T> runOnUiThread(FutureTask<T> task) {
+        if (runningOnUiThread()) {
+            task.run();
+        } else {
+            postOnUiThread(task);
+        }
+        return task;
+    }
+
+    /**
+     * Run the supplied Callable on the main thread. The method will block
+     * only if the current thread is the main thread.
+     *
+     * @param c The Callable to run
+     * @return A FutureTask wrapping the callable to retrieve results
+     */
+    public static <T> FutureTask<T> runOnUiThread(Callable<T> c) {
+        return runOnUiThread(new FutureTask<T>(c));
+    }
+
+    /**
+     * Run the supplied Runnable on the main thread. The method will block
+     * only if the current thread is the main thread.
+     *
+     * @param r The Runnable to run
+     */
+    public static void runOnUiThread(Runnable r) {
+        if (runningOnUiThread()) {
+            r.run();
+        } else {
+            LazyHolder.sUiThreadHandler.post(r);
+        }
+    }
+
+    /**
+     * Post the supplied FutureTask to run on the main thread. The method will
+     * not block, even if called on the UI thread.
+     *
+     * @param task The FutureTask to run
+     * @return The queried task (to aid inline construction)
+     */
+    public static <T> FutureTask<T> postOnUiThread(FutureTask<T> task) {
+        LazyHolder.sUiThreadHandler.post(task);
+        return task;
+    }
+
+    /**
+     * Post the supplied Runnable to run on the main thread. The method will
+     * not block, even if called on the UI thread.
+     *
+     * @param task The Runnable to run
+     */
+    public static void postOnUiThread(Runnable r) {
+        LazyHolder.sUiThreadHandler.post(r);
+    }
+
+    /**
+     * Asserts that the current thread is running on the main thread.
+     */
+    public static void assertOnUiThread() {
+        assert runningOnUiThread();
+    }
+
+    /**
+     * @return true iff the current thread is the main (UI) thread.
+     */
+    public static boolean runningOnUiThread() {
+      return Looper.getMainLooper() == Looper.myLooper();
+    }
+
+    private static class LazyHolder {
+        private static Handler sUiThreadHandler = new Handler(Looper.getMainLooper());
+    }
+}
diff --git a/src/base/android/java/src/org/chromium/base/WeakContext.java b/src/base/android/java/src/org/chromium/base/WeakContext.java
new file mode 100644
index 0000000..d660cc9
--- /dev/null
+++ b/src/base/android/java/src/org/chromium/base/WeakContext.java
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.content.Context;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.Callable;
+
+// Holds a WeakReference to Context to allow it to be GC'd.
+// Also provides utility functions to getSystemService from the UI or any
+// other thread (may return null, if the Context has been nullified).
+public class WeakContext {
+    private static WeakReference<Context> sWeakContext;
+
+    public static void initializeWeakContext(final Context context) {
+        sWeakContext = new WeakReference<Context>(context);
+    }
+
+    public static Context getContext() {
+        return sWeakContext.get();
+    }
+
+    // Returns a system service. May be called from any thread.
+    // If necessary, it will send a message to the main thread to acquire the
+    // service, and block waiting for it to complete.
+    // May return null if context is no longer available.
+    public static Object getSystemService(final String name) {
+        final Context context = sWeakContext.get();
+        if (context == null) {
+            return null;
+        }
+        if (ThreadUtils.runningOnUiThread()) {
+            return context.getSystemService(name);
+        }
+        return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Object>() {
+          @Override
+          public Object call() {
+            return context.getSystemService(name);
+          }
+        });
+    }
+}
diff --git a/src/base/android/jni_android.cc b/src/base/android/jni_android.cc
new file mode 100644
index 0000000..fdc2170
--- /dev/null
+++ b/src/base/android/jni_android.cc
@@ -0,0 +1,327 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_android.h"
+
+#include <map>
+
+#include "base/android/build_info.h"
+#include "base/android/jni_string.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/platform_thread.h"
+
+namespace {
+using base::android::GetClass;
+using base::android::MethodID;
+using base::android::ScopedJavaLocalRef;
+
+struct MethodIdentifier {
+  const char* class_name;
+  const char* method;
+  const char* jni_signature;
+
+  bool operator<(const MethodIdentifier& other) const {
+    int r = strcmp(class_name, other.class_name);
+    if (r < 0) {
+      return true;
+    } else if (r > 0) {
+      return false;
+    }
+
+    r = strcmp(method, other.method);
+    if (r < 0) {
+      return true;
+    } else if (r > 0) {
+      return false;
+    }
+
+    return strcmp(jni_signature, other.jni_signature) < 0;
+  }
+};
+
+typedef std::map<MethodIdentifier, jmethodID> MethodIDMap;
+
+const base::subtle::AtomicWord kUnlocked = 0;
+const base::subtle::AtomicWord kLocked = 1;
+base::subtle::AtomicWord g_method_id_map_lock = kUnlocked;
+JavaVM* g_jvm = NULL;
+// Leak the global app context, as it is used from a non-joinable worker thread
+// that may still be running at shutdown. There is no harm in doing this.
+base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky
+    g_application_context = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<MethodIDMap> g_method_id_map = LAZY_INSTANCE_INITIALIZER;
+
+std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) {
+  ScopedJavaLocalRef<jclass> throwable_clazz =
+      GetClass(env, "java/lang/Throwable");
+  jmethodID throwable_printstacktrace =
+      MethodID::Get<MethodID::TYPE_INSTANCE>(
+          env, throwable_clazz.obj(), "printStackTrace",
+          "(Ljava/io/PrintStream;)V");
+
+  // Create an instance of ByteArrayOutputStream.
+  ScopedJavaLocalRef<jclass> bytearray_output_stream_clazz =
+      GetClass(env, "java/io/ByteArrayOutputStream");
+  jmethodID bytearray_output_stream_constructor =
+      MethodID::Get<MethodID::TYPE_INSTANCE>(
+          env, bytearray_output_stream_clazz.obj(), "<init>", "()V");
+  jmethodID bytearray_output_stream_tostring =
+      MethodID::Get<MethodID::TYPE_INSTANCE>(
+          env, bytearray_output_stream_clazz.obj(), "toString",
+          "()Ljava/lang/String;");
+  ScopedJavaLocalRef<jobject> bytearray_output_stream(env,
+      env->NewObject(bytearray_output_stream_clazz.obj(),
+                     bytearray_output_stream_constructor));
+
+  // Create an instance of PrintStream.
+  ScopedJavaLocalRef<jclass> printstream_clazz =
+      GetClass(env, "java/io/PrintStream");
+  jmethodID printstream_constructor =
+      MethodID::Get<MethodID::TYPE_INSTANCE>(
+          env, printstream_clazz.obj(), "<init>",
+          "(Ljava/io/OutputStream;)V");
+  ScopedJavaLocalRef<jobject> printstream(env,
+      env->NewObject(printstream_clazz.obj(), printstream_constructor,
+                     bytearray_output_stream.obj()));
+
+  // Call Throwable.printStackTrace(PrintStream)
+  env->CallVoidMethod(java_throwable, throwable_printstacktrace,
+      printstream.obj());
+
+  // Call ByteArrayOutputStream.toString()
+  ScopedJavaLocalRef<jstring> exception_string(
+      env, static_cast<jstring>(
+          env->CallObjectMethod(bytearray_output_stream.obj(),
+                                bytearray_output_stream_tostring)));
+
+  return ConvertJavaStringToUTF8(exception_string);
+}
+
+}  // namespace
+
+namespace base {
+namespace android {
+
+JNIEnv* AttachCurrentThread() {
+  DCHECK(g_jvm);
+  JNIEnv* env = NULL;
+  jint ret = g_jvm->AttachCurrentThread(&env, NULL);
+  DCHECK_EQ(JNI_OK, ret);
+  return env;
+}
+
+void DetachFromVM() {
+  // Ignore the return value, if the thread is not attached, DetachCurrentThread
+  // will fail. But it is ok as the native thread may never be attached.
+  if (g_jvm)
+    g_jvm->DetachCurrentThread();
+}
+
+void InitVM(JavaVM* vm) {
+  DCHECK(!g_jvm);
+  g_jvm = vm;
+}
+
+void InitApplicationContext(const JavaRef<jobject>& context) {
+  DCHECK(g_application_context.Get().is_null());
+  g_application_context.Get().Reset(context);
+}
+
+const jobject GetApplicationContext() {
+  DCHECK(!g_application_context.Get().is_null());
+  return g_application_context.Get().obj();
+}
+
+ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) {
+  return ScopedJavaLocalRef<jclass>(env, GetUnscopedClass(env, class_name));
+}
+
+jclass GetUnscopedClass(JNIEnv* env, const char* class_name) {
+  jclass clazz = env->FindClass(class_name);
+  CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name;
+  return clazz;
+}
+
+bool HasClass(JNIEnv* env, const char* class_name) {
+  ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name));
+  if (!clazz.obj()) {
+    ClearException(env);
+    return false;
+  }
+  bool error = ClearException(env);
+  DCHECK(!error);
+  return true;
+}
+
+template<MethodID::Type type>
+jmethodID MethodID::Get(JNIEnv* env,
+                        jclass clazz,
+                        const char* method_name,
+                        const char* jni_signature) {
+  jmethodID id = type == TYPE_STATIC ?
+      env->GetStaticMethodID(clazz, method_name, jni_signature) :
+      env->GetMethodID(clazz, method_name, jni_signature);
+  CHECK(base::android::ClearException(env) || id) <<
+      "Failed to find " <<
+      (type == TYPE_STATIC ? "static " : "") <<
+      "method " << method_name << " " << jni_signature;
+  return id;
+}
+
+// If |atomic_method_id| set, it'll return immediately. Otherwise, it'll call
+// into ::Get() above. If there's a race, it's ok since the values are the same
+// (and the duplicated effort will happen only once).
+template<MethodID::Type type>
+jmethodID MethodID::LazyGet(JNIEnv* env,
+                            jclass clazz,
+                            const char* method_name,
+                            const char* jni_signature,
+                            base::subtle::AtomicWord* atomic_method_id) {
+  COMPILE_ASSERT(sizeof(subtle::AtomicWord) >= sizeof(jmethodID),
+                 AtomicWord_SmallerThan_jMethodID);
+  subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_method_id);
+  if (value)
+    return reinterpret_cast<jmethodID>(value);
+  jmethodID id = MethodID::Get<type>(env, clazz, method_name, jni_signature);
+  base::subtle::Release_Store(
+      atomic_method_id, reinterpret_cast<subtle::AtomicWord>(id));
+  return id;
+}
+
+// Various template instantiations.
+template jmethodID MethodID::Get<MethodID::TYPE_STATIC>(
+    JNIEnv* env, jclass clazz, const char* method_name,
+    const char* jni_signature);
+
+template jmethodID MethodID::Get<MethodID::TYPE_INSTANCE>(
+    JNIEnv* env, jclass clazz, const char* method_name,
+    const char* jni_signature);
+
+template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>(
+    JNIEnv* env, jclass clazz, const char* method_name,
+    const char* jni_signature, base::subtle::AtomicWord* atomic_method_id);
+
+template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
+    JNIEnv* env, jclass clazz, const char* method_name,
+    const char* jni_signature, base::subtle::AtomicWord* atomic_method_id);
+
+jfieldID GetFieldID(JNIEnv* env,
+                    const JavaRef<jclass>& clazz,
+                    const char* field_name,
+                    const char* jni_signature) {
+  jfieldID field_id = env->GetFieldID(clazz.obj(), field_name, jni_signature);
+  CHECK(!ClearException(env) && field_id) << "Failed to find field " <<
+      field_name << " " << jni_signature;
+  return field_id;
+}
+
+bool HasField(JNIEnv* env,
+              const JavaRef<jclass>& clazz,
+              const char* field_name,
+              const char* jni_signature) {
+  jfieldID field_id = env->GetFieldID(clazz.obj(), field_name, jni_signature);
+  if (!field_id) {
+    ClearException(env);
+    return false;
+  }
+  bool error = ClearException(env);
+  DCHECK(!error);
+  return true;
+}
+
+jfieldID GetStaticFieldID(JNIEnv* env,
+                          const JavaRef<jclass>& clazz,
+                          const char* field_name,
+                          const char* jni_signature) {
+  jfieldID field_id =
+      env->GetStaticFieldID(clazz.obj(), field_name, jni_signature);
+  CHECK(!ClearException(env) && field_id) << "Failed to find static field " <<
+      field_name << " " << jni_signature;
+  return field_id;
+}
+
+jmethodID GetMethodIDFromClassName(JNIEnv* env,
+                                   const char* class_name,
+                                   const char* method,
+                                   const char* jni_signature) {
+  MethodIdentifier key;
+  key.class_name = class_name;
+  key.method = method;
+  key.jni_signature = jni_signature;
+
+  MethodIDMap* map = g_method_id_map.Pointer();
+  bool found = false;
+
+  while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
+                                              kUnlocked,
+                                              kLocked) != kUnlocked) {
+    base::PlatformThread::YieldCurrentThread();
+  }
+  MethodIDMap::const_iterator iter = map->find(key);
+  if (iter != map->end()) {
+    found = true;
+  }
+  base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
+
+  // Addition to the map does not invalidate this iterator.
+  if (found) {
+    return iter->second;
+  }
+
+  ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name));
+  jmethodID id = MethodID::Get<MethodID::TYPE_INSTANCE>(
+      env, clazz.obj(), method, jni_signature);
+
+  while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
+                                              kUnlocked,
+                                              kLocked) != kUnlocked) {
+    base::PlatformThread::YieldCurrentThread();
+  }
+  // Another thread may have populated the map already.
+  std::pair<MethodIDMap::const_iterator, bool> result =
+      map->insert(std::make_pair(key, id));
+  DCHECK_EQ(id, result.first->second);
+  base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
+
+  return id;
+}
+
+bool HasException(JNIEnv* env) {
+  return env->ExceptionCheck() != JNI_FALSE;
+}
+
+bool ClearException(JNIEnv* env) {
+  if (!HasException(env))
+    return false;
+  env->ExceptionDescribe();
+  env->ExceptionClear();
+  return true;
+}
+
+void CheckException(JNIEnv* env) {
+  if (!HasException(env)) return;
+
+  // Exception has been found, might as well tell breakpad about it.
+  jthrowable java_throwable = env->ExceptionOccurred();
+  if (!java_throwable) {
+    // Do nothing but return false.
+    CHECK(false);
+  }
+
+  // Clear the pending exception, since a local reference is now held.
+  env->ExceptionDescribe();
+  env->ExceptionClear();
+
+  // Set the exception_string in BuildInfo so that breakpad can read it.
+  // RVO should avoid any extra copies of the exception string.
+  base::android::BuildInfo::GetInstance()->set_java_exception_info(
+      GetJavaExceptionInfo(env, java_throwable));
+
+  // Now, feel good about it and die.
+  CHECK(false);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/jni_android.h b/src/base/android/jni_android.h
new file mode 100644
index 0000000..16b85af
--- /dev/null
+++ b/src/base/android/jni_android.h
@@ -0,0 +1,137 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_JNI_ANDROID_H_
+#define BASE_ANDROID_JNI_ANDROID_H_
+
+#include <jni.h>
+#include <sys/types.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/atomicops.h"
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+
+namespace base {
+namespace android {
+
+// Used to mark symbols to be exported in a shared library's symbol table.
+#define JNI_EXPORT __attribute__ ((visibility("default")))
+
+// Contains the registration method information for initializing JNI bindings.
+struct RegistrationMethod {
+  const char* name;
+  bool (*func)(JNIEnv* env);
+};
+
+// Attach the current thread to the VM (if necessary) and return the JNIEnv*.
+BASE_EXPORT JNIEnv* AttachCurrentThread();
+
+// Detach the current thread from VM if it is attached.
+BASE_EXPORT void DetachFromVM();
+
+// Initializes the global JVM. It is not necessarily called before
+// InitApplicationContext().
+BASE_EXPORT void InitVM(JavaVM* vm);
+
+// Initializes the global application context object. The |context| can be any
+// valid reference to the application context. Internally holds a global ref to
+// the context. InitVM and InitApplicationContext maybe called in either order.
+BASE_EXPORT void InitApplicationContext(const JavaRef<jobject>& context);
+
+// Gets a global ref to the application context set with
+// InitApplicationContext(). Ownership is retained by the function - the caller
+// must NOT release it.
+const BASE_EXPORT jobject GetApplicationContext();
+
+// Finds the class named |class_name| and returns it.
+// Use this method instead of invoking directly the JNI FindClass method (to
+// prevent leaking local references).
+// This method triggers a fatal assertion if the class could not be found.
+// Use HasClass if you need to check whether the class exists.
+BASE_EXPORT ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env,
+                                                const char* class_name);
+
+// Similar to the above, but the caller is responsible to manage the jclass
+// lifetime.
+BASE_EXPORT jclass GetUnscopedClass(JNIEnv* env,
+                                    const char* class_name) WARN_UNUSED_RESULT;
+
+// Returns true iff the class |class_name| could be found.
+BASE_EXPORT bool HasClass(JNIEnv* env, const char* class_name);
+
+// This class is a wrapper for JNIEnv Get(Static)MethodID.
+class BASE_EXPORT MethodID {
+ public:
+  enum Type {
+    TYPE_STATIC,
+    TYPE_INSTANCE,
+  };
+
+  // Returns the method ID for the method with the specified name and signature.
+  // This method triggers a fatal assertion if the method could not be found.
+  template<Type type>
+  static jmethodID Get(JNIEnv* env,
+                       jclass clazz,
+                       const char* method_name,
+                       const char* jni_signature);
+
+  // The caller is responsible to zero-initialize |atomic_method_id|.
+  // It's fine to simultaneously call this on multiple threads referencing the
+  // same |atomic_method_id|.
+  template<Type type>
+  static jmethodID LazyGet(JNIEnv* env,
+                           jclass clazz,
+                           const char* method_name,
+                           const char* jni_signature,
+                           base::subtle::AtomicWord* atomic_method_id);
+};
+
+// Gets the method ID from the class name. Clears the pending Java exception
+// and returns NULL if the method is not found. Caches results. Note that
+// MethodID::Get() above avoids a class lookup, but does not cache results.
+// Strings passed to this function are held in the cache and MUST remain valid
+// beyond the duration of all future calls to this function, across all
+// threads. In practice, this means that the function should only be used with
+// string constants.
+BASE_EXPORT jmethodID GetMethodIDFromClassName(JNIEnv* env,
+                                               const char* class_name,
+                                               const char* method,
+                                               const char* jni_signature);
+
+// Gets the field ID for a class field.
+// This method triggers a fatal assertion if the field could not be found.
+BASE_EXPORT jfieldID GetFieldID(JNIEnv* env,
+                                const JavaRef<jclass>& clazz,
+                                const char* field_name,
+                                const char* jni_signature);
+
+// Returns true if |clazz| as a field with the given name and signature.
+// TODO(jcivelli): Determine whether we explicitly have to pass the environment.
+BASE_EXPORT bool HasField(JNIEnv* env,
+                          const JavaRef<jclass>& clazz,
+                          const char* field_name,
+                          const char* jni_signature);
+
+// Gets the field ID for a static class field.
+// This method triggers a fatal assertion if the field could not be found.
+BASE_EXPORT jfieldID GetStaticFieldID(JNIEnv* env,
+                                      const JavaRef<jclass>& clazz,
+                                      const char* field_name,
+                                      const char* jni_signature);
+
+// Returns true if an exception is pending in the provided JNIEnv*.
+BASE_EXPORT bool HasException(JNIEnv* env);
+
+// If an exception is pending in the provided JNIEnv*, this function clears it
+// and returns true.
+BASE_EXPORT bool ClearException(JNIEnv* env);
+
+// This function will call CHECK() macro if there's any pending exception.
+BASE_EXPORT void CheckException(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_JNI_ANDROID_H_
diff --git a/src/base/android/jni_android_unittest.cc b/src/base/android/jni_android_unittest.cc
new file mode 100644
index 0000000..920b395
--- /dev/null
+++ b/src/base/android/jni_android_unittest.cc
@@ -0,0 +1,141 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_android.h"
+
+#include "base/at_exit.h"
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace android {
+
+namespace {
+
+const char kJavaLangObject[] = "java/lang/Object";
+const char kGetClass[] = "getClass";
+const char kToString[] = "toString";
+const char kReturningJavaLangClass[] = "()Ljava/lang/Class;";
+const char kReturningJavaLangString[] = "()Ljava/lang/String;";
+
+const char* g_last_method;
+const char* g_last_jni_signature;
+jmethodID g_last_method_id;
+
+const JNINativeInterface* g_previous_functions;
+
+jmethodID GetMethodIDWrapper(JNIEnv* env, jclass clazz, const char* method,
+                             const char* jni_signature) {
+  g_last_method = method;
+  g_last_jni_signature = jni_signature;
+  g_last_method_id = g_previous_functions->GetMethodID(env, clazz, method,
+                                                       jni_signature);
+  return g_last_method_id;
+}
+
+}  // namespace
+
+class JNIAndroidTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    JNIEnv* env = AttachCurrentThread();
+    g_previous_functions = env->functions;
+    hooked_functions = *g_previous_functions;
+    env->functions = &hooked_functions;
+    hooked_functions.GetMethodID = &GetMethodIDWrapper;
+  }
+
+  virtual void TearDown() {
+    JNIEnv* env = AttachCurrentThread();
+    env->functions = g_previous_functions;
+    Reset();
+  }
+
+  void Reset() {
+    g_last_method = 0;
+    g_last_jni_signature = 0;
+    g_last_method_id = NULL;
+  }
+  // Needed to cleanup the cached method map in the implementation between
+  // runs (e.g. if using --gtest_repeat)
+  base::ShadowingAtExitManager exit_manager;
+  // From JellyBean release, the instance of this struct provided in JNIEnv is
+  // read-only, so we deep copy it to allow individual functions to be hooked.
+  JNINativeInterface hooked_functions;
+};
+
+TEST_F(JNIAndroidTest, GetMethodIDFromClassNameCaching) {
+  JNIEnv* env = AttachCurrentThread();
+
+  Reset();
+  jmethodID id1 = GetMethodIDFromClassName(env, kJavaLangObject, kGetClass,
+                                           kReturningJavaLangClass);
+  EXPECT_STREQ(kGetClass, g_last_method);
+  EXPECT_STREQ(kReturningJavaLangClass, g_last_jni_signature);
+  EXPECT_EQ(g_last_method_id, id1);
+
+  Reset();
+  jmethodID id2 = GetMethodIDFromClassName(env, kJavaLangObject, kGetClass,
+                                           kReturningJavaLangClass);
+  EXPECT_STREQ(0, g_last_method);
+  EXPECT_STREQ(0, g_last_jni_signature);
+  EXPECT_EQ(NULL, g_last_method_id);
+  EXPECT_EQ(id1, id2);
+
+  Reset();
+  jmethodID id3 = GetMethodIDFromClassName(env, kJavaLangObject, kToString,
+                                           kReturningJavaLangString);
+  EXPECT_STREQ(kToString, g_last_method);
+  EXPECT_STREQ(kReturningJavaLangString, g_last_jni_signature);
+  EXPECT_EQ(g_last_method_id, id3);
+}
+
+namespace {
+
+base::subtle::AtomicWord g_atomic_id = 0;
+int LazyMethodIDCall(JNIEnv* env, jclass clazz, int p) {
+  jmethodID id = base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_STATIC>(
+      env, clazz,
+      "abs",
+      "(I)I",
+      &g_atomic_id);
+
+  return env->CallStaticIntMethod(clazz, id, p);
+}
+
+int MethodIDCall(JNIEnv* env, jclass clazz, jmethodID id, int p) {
+  return env->CallStaticIntMethod(clazz, id, p);
+}
+
+}  // namespace
+
+TEST(JNIAndroidMicrobenchmark, MethodId) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jclass> clazz(GetClass(env, "java/lang/Math"));
+  base::Time start_lazy = base::Time::Now();
+  int o = 0;
+  for (int i = 0; i < 1024; ++i)
+    o += LazyMethodIDCall(env, clazz.obj(), i);
+  base::Time end_lazy = base::Time::Now();
+
+  jmethodID id = reinterpret_cast<jmethodID>(g_atomic_id);
+  base::Time start = base::Time::Now();
+  for (int i = 0; i < 1024; ++i)
+    o += MethodIDCall(env, clazz.obj(), id, i);
+  base::Time end = base::Time::Now();
+
+  // On a Galaxy Nexus, results were in the range of:
+  // JNI LazyMethodIDCall (us) 1984
+  // JNI MethodIDCall (us) 1861
+  LOG(ERROR) << "JNI LazyMethodIDCall (us) " <<
+      base::TimeDelta(end_lazy - start_lazy).InMicroseconds();
+  LOG(ERROR) << "JNI MethodIDCall (us) " <<
+      base::TimeDelta(end - start).InMicroseconds();
+  LOG(ERROR) << "JNI " << o;
+}
+
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/jni_array.cc b/src/base/android/jni_array.cc
new file mode 100644
index 0000000..fe2aadb
--- /dev/null
+++ b/src/base/android/jni_array.cc
@@ -0,0 +1,153 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_array.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/logging.h"
+
+namespace base {
+namespace android {
+
+ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(
+    JNIEnv* env, const uint8* bytes, size_t len) {
+  jbyteArray byte_array = env->NewByteArray(len);
+  CheckException(env);
+  DCHECK(byte_array);
+
+  jbyte* elements = env->GetByteArrayElements(byte_array, NULL);
+  memcpy(elements, bytes, len);
+  env->ReleaseByteArrayElements(byte_array, elements, 0);
+  CheckException(env);
+
+  return ScopedJavaLocalRef<jbyteArray>(env, byte_array);
+}
+
+ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
+    JNIEnv* env, const std::vector<std::string>& v) {
+  ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B");
+  jobjectArray joa = env->NewObjectArray(v.size(),
+                                         byte_array_clazz.obj(), NULL);
+  CheckException(env);
+
+  for (size_t i = 0; i < v.size(); ++i) {
+    ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(env,
+        reinterpret_cast<const uint8*>(v[i].data()), v[i].length());
+    env->SetObjectArrayElement(joa, i, byte_array.obj());
+  }
+  return ScopedJavaLocalRef<jobjectArray>(env, joa);
+}
+
+ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
+    JNIEnv* env, const std::vector<std::string>& v) {
+  ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String");
+  jobjectArray joa = env->NewObjectArray(v.size(), string_clazz.obj(), NULL);
+  CheckException(env);
+
+  for (size_t i = 0; i < v.size(); ++i) {
+    ScopedJavaLocalRef<jstring> item = ConvertUTF8ToJavaString(env, v[i]);
+    env->SetObjectArrayElement(joa, i, item.obj());
+  }
+  return ScopedJavaLocalRef<jobjectArray>(env, joa);
+}
+
+ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
+    JNIEnv* env, const std::vector<string16>& v) {
+  ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String");
+  jobjectArray joa = env->NewObjectArray(v.size(), string_clazz.obj(), NULL);
+  CheckException(env);
+
+  for (size_t i = 0; i < v.size(); ++i) {
+    ScopedJavaLocalRef<jstring> item = ConvertUTF16ToJavaString(env, v[i]);
+    env->SetObjectArrayElement(joa, i, item.obj());
+  }
+  return ScopedJavaLocalRef<jobjectArray>(env, joa);
+}
+
+void AppendJavaStringArrayToStringVector(JNIEnv* env,
+                                         jobjectArray array,
+                                         std::vector<string16>* out) {
+  DCHECK(out);
+  if (!array)
+    return;
+  jsize len = env->GetArrayLength(array);
+  size_t back = out->size();
+  out->resize(back + len);
+  for (jsize i = 0; i < len; ++i) {
+    ScopedJavaLocalRef<jstring> str(env,
+        static_cast<jstring>(env->GetObjectArrayElement(array, i)));
+    ConvertJavaStringToUTF16(env, str.obj(), &((*out)[back + i]));
+  }
+}
+
+void AppendJavaStringArrayToStringVector(JNIEnv* env,
+                                         jobjectArray array,
+                                         std::vector<std::string>* out) {
+  DCHECK(out);
+  if (!array)
+    return;
+  jsize len = env->GetArrayLength(array);
+  size_t back = out->size();
+  out->resize(back + len);
+  for (jsize i = 0; i < len; ++i) {
+    ScopedJavaLocalRef<jstring> str(env,
+        static_cast<jstring>(env->GetObjectArrayElement(array, i)));
+    ConvertJavaStringToUTF8(env, str.obj(), &((*out)[back + i]));
+  }
+}
+
+void AppendJavaByteArrayToByteVector(JNIEnv* env,
+                                     jbyteArray byte_array,
+                                     std::vector<uint8>* out) {
+  DCHECK(out);
+  if (!byte_array)
+    return;
+  jsize len = env->GetArrayLength(byte_array);
+  jbyte* bytes = env->GetByteArrayElements(byte_array, NULL);
+  out->insert(out->end(), bytes, bytes + len);
+  env->ReleaseByteArrayElements(byte_array, bytes, JNI_ABORT);
+}
+
+void JavaByteArrayToByteVector(JNIEnv* env,
+                               jbyteArray byte_array,
+                               std::vector<uint8>* out) {
+  DCHECK(out);
+  out->clear();
+  AppendJavaByteArrayToByteVector(env, byte_array, out);
+}
+
+void JavaIntArrayToIntVector(JNIEnv* env,
+                             jintArray array,
+                             std::vector<int>* out) {
+  DCHECK(out);
+  out->clear();
+  jsize len = env->GetArrayLength(array);
+  jint* ints = env->GetIntArrayElements(array, NULL);
+  for (jsize i = 0; i < len; ++i) {
+    out->push_back(static_cast<int>(ints[i]));
+  }
+  env->ReleaseIntArrayElements(array, ints, JNI_ABORT);
+}
+
+void JavaArrayOfByteArrayToStringVector(
+    JNIEnv* env,
+    jobjectArray array,
+    std::vector<std::string>* out) {
+  DCHECK(out);
+  out->clear();
+  jsize len = env->GetArrayLength(array);
+  out->resize(len);
+  for (jsize i = 0; i < len; ++i) {
+    jbyteArray bytes_array = static_cast<jbyteArray>(
+        env->GetObjectArrayElement(array, i));
+    jsize bytes_len = env->GetArrayLength(bytes_array);
+    jbyte* bytes = env->GetByteArrayElements(bytes_array, NULL);
+    (*out)[i].assign(reinterpret_cast<const char*>(bytes), bytes_len);
+    env->ReleaseByteArrayElements(bytes_array, bytes, JNI_ABORT);
+  }
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/jni_array.h b/src/base/android/jni_array.h
new file mode 100644
index 0000000..fbc131e
--- /dev/null
+++ b/src/base/android/jni_array.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_JNI_ARRAY_H_
+#define BASE_ANDROID_JNI_ARRAY_H_
+
+#include <jni.h>
+#include <string>
+#include <vector>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/string16.h"
+
+namespace base {
+namespace android {
+
+// Returns a new Java byte array converted from the given bytes array.
+BASE_EXPORT ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(
+    JNIEnv* env, const uint8* bytes, size_t len);
+
+// Returns a array of Java byte array converted from |v|.
+BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
+    JNIEnv* env, const std::vector<std::string>& v);
+
+BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
+    JNIEnv* env,  const std::vector<std::string>& v);
+
+BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
+    JNIEnv* env,  const std::vector<string16>& v);
+
+// Converts a Java string array to a native array.
+BASE_EXPORT void AppendJavaStringArrayToStringVector(
+    JNIEnv* env,
+    jobjectArray array,
+    std::vector<string16>* out);
+
+BASE_EXPORT void AppendJavaStringArrayToStringVector(
+    JNIEnv* env,
+    jobjectArray array,
+    std::vector<std::string>* out);
+
+// Appends the Java bytes in |bytes_array| onto the end of |out|.
+BASE_EXPORT void AppendJavaByteArrayToByteVector(
+    JNIEnv* env,
+    jbyteArray byte_array,
+    std::vector<uint8>* out);
+
+// Replaces the content of |out| with the Java bytes in |bytes_array|.
+BASE_EXPORT void JavaByteArrayToByteVector(
+    JNIEnv* env,
+    jbyteArray byte_array,
+    std::vector<uint8>* out);
+
+// Replaces the content of |out| with the Java ints in |int_array|.
+BASE_EXPORT void JavaIntArrayToIntVector(
+    JNIEnv* env,
+    jintArray int_array,
+    std::vector<int>* out);
+
+// Assuming |array| is an byte[][] (array of byte arrays), replaces the
+// content of |out| with the corresponding vector of strings. No UTF-8
+// conversion is performed.
+void JavaArrayOfByteArrayToStringVector(
+    JNIEnv* env,
+    jobjectArray array,
+    std::vector<std::string>* out);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_JNI_ARRAY_H_
diff --git a/src/base/android/jni_array_unittest.cc b/src/base/android/jni_array_unittest.cc
new file mode 100644
index 0000000..a4e3025
--- /dev/null
+++ b/src/base/android/jni_array_unittest.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_array.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace android {
+
+TEST(JniArray, BasicConversions) {
+  const uint8 kBytes[] = { 0, 1, 2, 3 };
+  const size_t kLen = arraysize(kBytes);
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jbyteArray> bytes = ToJavaByteArray(env, kBytes, kLen);
+  ASSERT_TRUE(bytes.obj());
+
+  std::vector<uint8> vec(5);
+  JavaByteArrayToByteVector(env, bytes.obj(), &vec);
+  EXPECT_EQ(4U, vec.size());
+  EXPECT_EQ(std::vector<uint8>(kBytes, kBytes + kLen), vec);
+
+  AppendJavaByteArrayToByteVector(env, bytes.obj(), &vec);
+  EXPECT_EQ(8U, vec.size());
+}
+
+TEST(JniArray, JavaArrayOfByteArrayToStringVector) {
+  const int kMaxItems = 50;
+  JNIEnv* env = AttachCurrentThread();
+
+  // Create a byte[][] object.
+  ScopedJavaLocalRef<jclass> byte_array_clazz(env, env->FindClass("[B"));
+  ASSERT_TRUE(byte_array_clazz.obj());
+
+  ScopedJavaLocalRef<jobjectArray> array(
+      env, env->NewObjectArray(kMaxItems, byte_array_clazz.obj(), NULL));
+  ASSERT_TRUE(array.obj());
+
+  // Create kMaxItems byte buffers.
+  char text[16];
+  for (int i = 0; i < kMaxItems; ++i) {
+    snprintf(text, sizeof text, "%d", i);
+    ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(
+        env, reinterpret_cast<uint8*>(text),
+        static_cast<size_t>(strlen(text)));
+    ASSERT_TRUE(byte_array.obj());
+
+    env->SetObjectArrayElement(array.obj(), i, byte_array.obj());
+    ASSERT_FALSE(HasException(env));
+  }
+
+  // Convert to std::vector<std::string>, check the content.
+  std::vector<std::string> vec;
+  JavaArrayOfByteArrayToStringVector(env, array.obj(), &vec);
+
+  EXPECT_EQ(static_cast<size_t>(kMaxItems), vec.size());
+  for (int i = 0; i < kMaxItems; ++i) {
+    snprintf(text, sizeof text, "%d", i);
+    EXPECT_STREQ(text, vec[i].c_str());
+  }
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/jni_generator/SampleForTests.java b/src/base/android/jni_generator/SampleForTests.java
new file mode 100644
index 0000000..341f0ea
--- /dev/null
+++ b/src/base/android/jni_generator/SampleForTests.java
@@ -0,0 +1,171 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.example.jni_generator;
+
+import android.graphics.Rect;
+
+// This class serves as a reference test for the bindings generator, and as example documentation
+// for how to use the jni generator.
+// The C++ counter-part is sample_for_tests.cc.
+// jni_generator.gyp has a jni_generator_tests target that will:
+//   * Generate a header file for the JNI bindings based on this file.
+//   * Compile sample_for_tests.cc using the generated header file.
+//   * link a native executable to prove the generated header + cc file are self-contained.
+// All comments are informational only, and are ignored by the jni generator.
+//
+// This JNINamespace annotation indicates that all native methods should be
+// generated inside this namespace, including the native class that this
+// object binds to.
+@JNINamespace("base::android")
+class SampleForTests {
+  // Classes can store their C++ pointer counter part as an int that is normally initialized by
+  // calling out a nativeInit() function.
+  int nativePtr;
+
+  // You can define methods and attributes on the java class just like any other.
+  // Methods without the @CalledByNative annotation won't be exposed to JNI.
+  public SampleForTests() {
+  }
+
+  public void startExample() {
+      // Calls native code and holds a pointer to the C++ class.
+      nativePtr = nativeInit("myParam");
+  }
+
+  public void doStuff() {
+      // This will call CPPClass::Method() using nativePtr as a pointer to the object. This must be
+      // done to:
+      // * avoid leaks.
+      // * using finalizers are not allowed to destroy the cpp class.
+      nativeMethod(nativePtr);
+  }
+
+  public void finishExample() {
+      // We're done, so let's destroy nativePtr object.
+      nativeDestroy(nativePtr);
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // The following methods demonstrate exporting Java methods for invocation from C++ code.
+  // Java functions are mapping into C global functions by prefixing the method name with
+  // "Java_<Class>_"
+  // This is triggered by the @CalledByNative annotation; the methods may be named as you wish.
+
+  // Exported to C++ as:
+  //   Java_Example_javaMethod(JNIEnv* env, jobject obj, jint foo, jint bar)
+  // Typically the C++ code would have obtained the jobject via the Init() call described above.
+  @CalledByNative
+  public int javaMethod(int foo,
+                        int bar) {
+      return 0;
+  }
+
+  // Exported to C++ as Java_Example_staticJavaMethod(JNIEnv* env)
+  // Note no jobject argument, as it is static.
+  @CalledByNative
+  public static boolean staticJavaMethod() {
+      return true;
+  }
+
+  // No prefix, so this method is package private. It will still be exported.
+  @CalledByNative
+  void packagePrivateJavaMethod() {}
+
+  // Note the "Unchecked" suffix. By default, @CalledByNative will always generate bindings that
+  // call CheckException(). With "@CalledByNativeUnchecked", the client C++ code is responsible to
+  // call ClearException() and act as appropriate.
+  // See more details at the "@CalledByNativeUnchecked" annotation.
+  @CalledByNativeUnchecked
+  void methodThatThrowsException() throws Exception {}
+
+  // The generator is not confused by inline comments:
+  // @CalledByNative void thisShouldNotAppearInTheOutput();
+  // @CalledByNativeUnchecked public static void neitherShouldThis(int foo);
+
+  /**
+   * The generator is not confused by block comments:
+   * @CalledByNative void thisShouldNotAppearInTheOutputEither();
+   * @CalledByNativeUnchecked public static void andDefinitelyNotThis(int foo);
+   */
+
+  // String constants that look like comments don't confuse the generator:
+  private String arrgh = "*/*";
+
+  //------------------------------------------------------------------------------------------------
+  // Java fields which are accessed from C++ code only must be annotated with @AccessedByNative to
+  // prevent them being eliminated when unreferenced code is stripped.
+  @AccessedByNative
+  private int javaField;
+
+  //------------------------------------------------------------------------------------------------
+  // The following methods demonstrate declaring methods to call into C++ from Java.
+  // The generator detects the "native" and "static" keywords, the type and name of the first
+  // parameter, and the "native" prefix to the function name to determine the C++ function
+  // signatures. Besides these constraints the methods can be freely named.
+
+  // This declares a C++ function which the application code must implement:
+  //   static jint Init(JNIEnv* env, jobject obj);
+  // The jobject parameter refers back to this java side object instance.
+  // The implementation must return the pointer to the C++ object cast to jint.
+  // The caller of this method should store it, and supply it as a the nativeCPPClass param to
+  // subsequent native method calls (see the methods below that take an "int native..." as first
+  // param).
+  private native int nativeInit();
+
+  // This defines a function binding to the associated C++ class member function. The name is
+  // derived from |nativeDestroy| and |nativeCPPClass| to arrive at CPPClass::Destroy() (i.e. native
+  // prefixes stripped).
+  // The |nativeCPPClass| is automatically cast to type CPPClass* in order to obtain the object on
+  // which to invoke the member function.
+  private native void nativeDestroy(int nativeCPPClass);
+
+  // This declares a C++ function which the application code must implement:
+  //   static jdouble GetDoubleFunction(JNIEnv* env, jobject obj);
+  // The jobject parameter refers back to this java side object instance.
+  private native double nativeGetDoubleFunction();
+
+  // Similar to nativeGetDoubleFunction(), but here the C++ side will receive a jclass rather than
+  // jobject param, as the function is declared static.
+  private static native float nativeGetFloatFunction();
+
+  // This function takes a non-POD datatype. We have a list mapping them to their full classpath in
+  // jni_generator.py JavaParamToJni. If you require a new datatype, make sure you add to that
+  // function.
+  private native void nativeSetNonPODDatatype(Rect rect);
+
+  // This declares a C++ function which the application code must implement:
+  //   static ScopedJavaLocalRef<jobject> GetNonPODDatatype(JNIEnv* env, jobject obj);
+  // The jobject parameter refers back to this java side object instance.
+  // Note that it returns a ScopedJavaLocalRef<jobject> so that you don' have to worry about
+  // deleting the JNI local reference.  This is similar with Strings and arrays.
+  private native Object nativeGetNonPODDatatype();
+
+  // Similar to nativeDestroy above, this will cast nativeCPPClass into pointer of CPPClass type and
+  // call its Method member function.
+  private native int nativeMethod(int nativeCPPClass);
+
+  // Similar to nativeMethod above, but here the C++ fully qualified class name is taken from the
+  // annotation rather than parameter name, which can thus be chosen freely.
+  @NativeClassQualifiedName("CPPClass::InnerClass")
+  private native double nativeMethodOtherP0(int nativePtr);
+
+  // An inner class has some special attributes for annotation.
+  class InnerClass {
+    @CalledByNative("InnerClass")
+    public float JavaInnerMethod() {
+    }
+
+    @CalledByNative("InnerClass")
+    public static void javaInnerFunction() {
+    }
+
+    @NativeCall("InnerClass")
+    private static native int nativeInnerFunction();
+
+    @NativeCall("InnerClass")
+    private static native String nativeInnerMethod(int nativeCPPClass);
+
+  }
+}
diff --git a/src/base/android/jni_generator/golden_sample_for_tests_jni.h b/src/base/android/jni_generator/golden_sample_for_tests_jni.h
new file mode 100644
index 0000000..08f25a7
--- /dev/null
+++ b/src/base/android/jni_generator/golden_sample_for_tests_jni.h
@@ -0,0 +1,293 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     base/android/jni_generator/jni_generator_tests.py
+// For
+//     org/chromium/example/jni_generator/SampleForTests
+
+#ifndef org_chromium_example_jni_generator_SampleForTests_JNI
+#define org_chromium_example_jni_generator_SampleForTests_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kInnerClassClassPath[] =
+    "org/chromium/example/jni_generator/SampleForTests$InnerClass";
+const char kSampleForTestsClassPath[] =
+    "org/chromium/example/jni_generator/SampleForTests";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_InnerClass_clazz = NULL;
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_SampleForTests_clazz = NULL;
+}  // namespace
+
+namespace base {
+namespace android {
+
+static jint Init(JNIEnv* env, jobject obj);
+
+static jdouble GetDoubleFunction(JNIEnv* env, jobject obj);
+
+static jfloat GetFloatFunction(JNIEnv* env, jclass clazz);
+
+static void SetNonPODDatatype(JNIEnv* env, jobject obj,
+    jobject rect);
+
+static jobject GetNonPODDatatype(JNIEnv* env, jobject obj);
+
+static jint InnerFunction(JNIEnv* env, jclass clazz);
+
+// Step 2: method stubs.
+static void Destroy(JNIEnv* env, jobject obj,
+    jint nativeCPPClass) {
+  DCHECK(nativeCPPClass) << "Destroy";
+  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
+  return native->Destroy(env, obj);
+}
+
+static jint Method(JNIEnv* env, jobject obj,
+    jint nativeCPPClass) {
+  DCHECK(nativeCPPClass) << "Method";
+  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
+  return native->Method(env, obj);
+}
+
+static jdouble MethodOtherP0(JNIEnv* env, jobject obj,
+    jint nativePtr) {
+  DCHECK(nativePtr) << "MethodOtherP0";
+  CPPClass::InnerClass* native =
+      reinterpret_cast<CPPClass::InnerClass*>(nativePtr);
+  return native->MethodOtherP0(env, obj);
+}
+
+static jstring InnerMethod(JNIEnv* env, jobject obj,
+    jint nativeCPPClass) {
+  DCHECK(nativeCPPClass) << "InnerMethod";
+  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
+  return native->InnerMethod(env, obj).Release();
+}
+
+static base::subtle::AtomicWord g_SampleForTests_javaMethod = 0;
+static jint Java_SampleForTests_javaMethod(JNIEnv* env, jobject obj, jint foo,
+    jint bar) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_SampleForTests_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_SampleForTests_clazz,
+      "javaMethod",
+
+"("
+"I"
+"I"
+")"
+"I",
+      &g_SampleForTests_javaMethod);
+
+  jint ret =
+    env->CallIntMethod(obj,
+      method_id, foo, bar);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_SampleForTests_staticJavaMethod = 0;
+static jboolean Java_SampleForTests_staticJavaMethod(JNIEnv* env) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_SampleForTests_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_STATIC>(
+      env, g_SampleForTests_clazz,
+      "staticJavaMethod",
+
+"("
+")"
+"Z",
+      &g_SampleForTests_staticJavaMethod);
+
+  jboolean ret =
+    env->CallStaticBooleanMethod(g_SampleForTests_clazz,
+      method_id);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_SampleForTests_packagePrivateJavaMethod = 0;
+static void Java_SampleForTests_packagePrivateJavaMethod(JNIEnv* env, jobject
+    obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_SampleForTests_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_SampleForTests_clazz,
+      "packagePrivateJavaMethod",
+
+"("
+")"
+"V",
+      &g_SampleForTests_packagePrivateJavaMethod);
+
+  env->CallVoidMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+
+}
+
+static base::subtle::AtomicWord g_SampleForTests_methodThatThrowsException = 0;
+static void Java_SampleForTests_methodThatThrowsException(JNIEnv* env, jobject
+    obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_SampleForTests_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_SampleForTests_clazz,
+      "methodThatThrowsException",
+
+"("
+")"
+"V",
+      &g_SampleForTests_methodThatThrowsException);
+
+  env->CallVoidMethod(obj,
+      method_id);
+
+}
+
+static base::subtle::AtomicWord g_InnerClass_JavaInnerMethod = 0;
+static jfloat Java_InnerClass_JavaInnerMethod(JNIEnv* env, jobject obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InnerClass_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InnerClass_clazz,
+      "JavaInnerMethod",
+
+"("
+")"
+"F",
+      &g_InnerClass_JavaInnerMethod);
+
+  jfloat ret =
+    env->CallFloatMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_InnerClass_javaInnerFunction = 0;
+static void Java_InnerClass_javaInnerFunction(JNIEnv* env) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InnerClass_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_STATIC>(
+      env, g_InnerClass_clazz,
+      "javaInnerFunction",
+
+"("
+")"
+"V",
+      &g_InnerClass_javaInnerFunction);
+
+  env->CallStaticVoidMethod(g_InnerClass_clazz,
+      method_id);
+  base::android::CheckException(env);
+
+}
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_InnerClass_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kInnerClassClassPath)));
+  g_SampleForTests_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kSampleForTestsClassPath)));
+  static const JNINativeMethod kMethodsInnerClass[] = {
+    { "nativeInnerFunction",
+"("
+")"
+"I", reinterpret_cast<void*>(InnerFunction) },
+    { "nativeInnerMethod",
+"("
+"I"
+")"
+"Ljava/lang/String;", reinterpret_cast<void*>(InnerMethod) },
+  };
+  const int kMethodsInnerClassSize = arraysize(kMethodsInnerClass);
+
+  if (env->RegisterNatives(g_InnerClass_clazz,
+                           kMethodsInnerClass,
+                           kMethodsInnerClassSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  static const JNINativeMethod kMethodsSampleForTests[] = {
+    { "nativeInit",
+"("
+")"
+"I", reinterpret_cast<void*>(Init) },
+    { "nativeDestroy",
+"("
+"I"
+")"
+"V", reinterpret_cast<void*>(Destroy) },
+    { "nativeGetDoubleFunction",
+"("
+")"
+"D", reinterpret_cast<void*>(GetDoubleFunction) },
+    { "nativeGetFloatFunction",
+"("
+")"
+"F", reinterpret_cast<void*>(GetFloatFunction) },
+    { "nativeSetNonPODDatatype",
+"("
+"Landroid/graphics/Rect;"
+")"
+"V", reinterpret_cast<void*>(SetNonPODDatatype) },
+    { "nativeGetNonPODDatatype",
+"("
+")"
+"Ljava/lang/Object;", reinterpret_cast<void*>(GetNonPODDatatype) },
+    { "nativeMethod",
+"("
+"I"
+")"
+"I", reinterpret_cast<void*>(Method) },
+    { "nativeMethodOtherP0",
+"("
+"I"
+")"
+"D", reinterpret_cast<void*>(MethodOtherP0) },
+  };
+  const int kMethodsSampleForTestsSize = arraysize(kMethodsSampleForTests);
+
+  if (env->RegisterNatives(g_SampleForTests_clazz,
+                           kMethodsSampleForTests,
+                           kMethodsSampleForTestsSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  return true;
+}
+}  // namespace android
+}  // namespace base
+
+#endif  // org_chromium_example_jni_generator_SampleForTests_JNI
diff --git a/src/base/android/jni_generator/jni_generator.gyp b/src/base/android/jni_generator/jni_generator.gyp
new file mode 100644
index 0000000..dc32d22
--- /dev/null
+++ b/src/base/android/jni_generator/jni_generator.gyp
@@ -0,0 +1,55 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'jni_generator_py_tests',
+      'type': 'none',
+      'actions': [
+        {
+          'action_name': 'run_jni_generator_py_tests',
+          'inputs': [
+            'jni_generator.py',
+            'jni_generator_tests.py',
+            'SampleForTests.java',
+            'golden_sample_for_tests_jni.h',
+          ],
+          'outputs': [
+            '',
+          ],
+          'action': [
+            'python', 'jni_generator_tests.py',
+          ],
+        },
+      ],
+    },
+    {
+      'target_name': 'jni_sample_header',
+      'type': 'none',
+      'sources': [
+        'SampleForTests.java',
+      ],
+      'variables': {
+        'jni_gen_dir': 'base',
+      },
+      'includes': [ '../../../build/jni_generator.gypi' ],
+    },
+    {
+      'target_name': 'jni_generator_tests',
+      'type': 'executable',
+      'dependencies': [
+        '../../base.gyp:test_support_base',
+        'jni_generator_py_tests',
+        'jni_sample_header',
+      ],
+      'include_dirs': [
+        '<(SHARED_INTERMEDIATE_DIR)/base',
+      ],
+      'sources': [
+        'sample_for_tests.cc',
+      ],
+    },
+  ],
+}
diff --git a/src/base/android/jni_generator/jni_generator.py b/src/base/android/jni_generator/jni_generator.py
new file mode 100755
index 0000000..18312c6
--- /dev/null
+++ b/src/base/android/jni_generator/jni_generator.py
@@ -0,0 +1,1005 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Extracts native methods from a Java file and generates the JNI bindings.
+If you change this, please run and update the tests."""
+
+import collections
+import optparse
+import os
+import re
+import string
+from string import Template
+import subprocess
+import sys
+import textwrap
+import zipfile
+
+
+class ParseError(Exception):
+  """Exception thrown when we can't parse the input file."""
+
+  def __init__(self, description, *context_lines):
+    Exception.__init__(self)
+    self.description = description
+    self.context_lines = context_lines
+
+  def __str__(self):
+    context = '\n'.join(self.context_lines)
+    return '***\nERROR: %s\n\n%s\n***' % (self.description, context)
+
+
+class Param(object):
+  """Describes a param for a method, either java or native."""
+
+  def __init__(self, **kwargs):
+    self.datatype = kwargs['datatype']
+    self.name = kwargs['name']
+
+
+class NativeMethod(object):
+  """Describes a C/C++ method that is called by Java code"""
+
+  def __init__(self, **kwargs):
+    self.static = kwargs['static']
+    self.java_class_name = kwargs['java_class_name']
+    self.return_type = kwargs['return_type']
+    self.name = kwargs['name']
+    self.params = kwargs['params']
+    if self.params:
+      assert type(self.params) is list
+      assert type(self.params[0]) is Param
+    if (self.params and
+        self.params[0].datatype == 'int' and
+        self.params[0].name.startswith('native')):
+      self.type = 'method'
+      self.p0_type = self.params[0].name[len('native'):]
+      if kwargs.get('native_class_name'):
+        self.p0_type = kwargs['native_class_name']
+    else:
+      self.type = 'function'
+    self.method_id_var_name = kwargs.get('method_id_var_name', None)
+
+
+class CalledByNative(object):
+  """Describes a java method exported to c/c++"""
+
+  def __init__(self, **kwargs):
+    self.system_class = kwargs['system_class']
+    self.unchecked = kwargs['unchecked']
+    self.static = kwargs['static']
+    self.java_class_name = kwargs['java_class_name']
+    self.return_type = kwargs['return_type']
+    self.name = kwargs['name']
+    self.params = kwargs['params']
+    self.method_id_var_name = kwargs.get('method_id_var_name', None)
+    self.is_constructor = kwargs.get('is_constructor', False)
+    self.env_call = GetEnvCall(self.is_constructor, self.static,
+                               self.return_type)
+    self.static_cast = GetStaticCastForReturnType(self.return_type)
+
+
+def JavaDataTypeToC(java_type):
+  """Returns a C datatype for the given java type."""
+  java_pod_type_map = {
+      'int': 'jint',
+      'byte': 'jbyte',
+      'boolean': 'jboolean',
+      'long': 'jlong',
+      'double': 'jdouble',
+      'float': 'jfloat',
+  }
+  java_type_map = {
+      'void': 'void',
+      'String': 'jstring',
+      'java/lang/String': 'jstring',
+      'Class': 'jclass',
+      'java/lang/Class': 'jclass',
+  }
+
+  if java_type in java_pod_type_map:
+    return java_pod_type_map[java_type]
+  elif java_type in java_type_map:
+    return java_type_map[java_type]
+  elif java_type.endswith('[]'):
+    if java_type[:-2] in java_pod_type_map:
+      return java_pod_type_map[java_type[:-2]] + 'Array'
+    return 'jobjectArray'
+  else:
+    return 'jobject'
+
+
+class JniParams(object):
+  _imports = []
+  _fully_qualified_class = ''
+  _package = ''
+  _inner_classes = []
+
+  @staticmethod
+  def SetFullyQualifiedClass(fully_qualified_class):
+    JniParams._fully_qualified_class = 'L' + fully_qualified_class
+    JniParams._package = '/'.join(fully_qualified_class.split('/')[:-1])
+
+  @staticmethod
+  def ExtractImportsAndInnerClasses(contents):
+    contents = contents.replace('\n', '')
+    re_import = re.compile(r'import.*?(?P<class>\S*?);')
+    for match in re.finditer(re_import, contents):
+      JniParams._imports += ['L' + match.group('class').replace('.', '/')]
+
+    re_inner = re.compile(r'(class|interface)\s+?(?P<name>\w+?)\W')
+    for match in re.finditer(re_inner, contents):
+      inner = match.group('name')
+      if not JniParams._fully_qualified_class.endswith(inner):
+        JniParams._inner_classes += [JniParams._fully_qualified_class + '$' +
+                                     inner]
+
+  @staticmethod
+  def JavaToJni(param):
+    """Converts a java param into a JNI signature type."""
+    pod_param_map = {
+        'int': 'I',
+        'boolean': 'Z',
+        'long': 'J',
+        'double': 'D',
+        'float': 'F',
+        'byte': 'B',
+        'void': 'V',
+    }
+    object_param_list = [
+        'Ljava/lang/Boolean',
+        'Ljava/lang/Integer',
+        'Ljava/lang/Long',
+        'Ljava/lang/Object',
+        'Ljava/lang/String',
+        'Ljava/lang/Class',
+    ]
+    if param == 'byte[][]':
+      return '[[B'
+    prefix = ''
+    # Array?
+    if param[-2:] == '[]':
+      prefix = '['
+      param = param[:-2]
+    # Generic?
+    if '<' in param:
+      param = param[:param.index('<')]
+    if param in pod_param_map:
+      return prefix + pod_param_map[param]
+    if '/' in param:
+      # Coming from javap, use the fully qualified param directly.
+      return 'L' + param + ';'
+    for qualified_name in (object_param_list +
+                           [JniParams._fully_qualified_class] +
+                           JniParams._inner_classes):
+      if (qualified_name.endswith('/' + param) or
+          qualified_name.endswith('$' + param.replace('.', '$')) or
+          qualified_name == 'L' + param):
+        return prefix + qualified_name + ';'
+
+    # Is it from an import? (e.g. referecing Class from import pkg.Class;
+    # note that referencing an inner class Inner from import pkg.Class.Inner
+    # is not supported).
+    for qualified_name in JniParams._imports:
+      if qualified_name.endswith('/' + param):
+        # Ensure it's not an inner class.
+        components = qualified_name.split('/')
+        if len(components) > 2 and components[-2][0].isupper():
+          raise SyntaxError('Inner class (%s) can not be imported '
+                            'and used by JNI (%s). Please import the outer '
+                            'class and use Outer.Inner instead.' %
+                            (qualified_name, param))
+        return prefix + qualified_name + ';'
+
+    # Is it an inner class from an outer class import? (e.g. referencing
+    # Class.Inner from import pkg.Class).
+    if '.' in param:
+      components = param.split('.')
+      outer = '/'.join(components[:-1])
+      inner = components[-1]
+      for qualified_name in JniParams._imports:
+        if qualified_name.endswith('/' + outer):
+          return prefix + qualified_name + '$' + inner
+
+    # Type not found, falling back to same package as this class.
+    return prefix + 'L' + JniParams._package + '/' + param + ';'
+
+  @staticmethod
+  def Signature(params, returns, wrap):
+    """Returns the JNI signature for the given datatypes."""
+    items = ['(']
+    items += [JniParams.JavaToJni(param.datatype) for param in params]
+    items += [')']
+    items += [JniParams.JavaToJni(returns)]
+    if wrap:
+      return '\n' + '\n'.join(['"' + item + '"' for item in items])
+    else:
+      return '"' + ''.join(items) + '"'
+
+  @staticmethod
+  def Parse(params):
+    """Parses the params into a list of Param objects."""
+    if not params:
+      return []
+    ret = []
+    for p in [p.strip() for p in params.split(',')]:
+      items = p.split(' ')
+      if 'final' in items:
+        items.remove('final')
+      param = Param(
+          datatype=items[0],
+          name=(items[1] if len(items) > 1 else 'p%s' % len(ret)),
+      )
+      ret += [param]
+    return ret
+
+
+def ExtractJNINamespace(contents):
+  re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)')
+  m = re.findall(re_jni_namespace, contents)
+  if not m:
+    return ''
+  return m[0]
+
+
+def ExtractFullyQualifiedJavaClassName(java_file_name, contents):
+  re_package = re.compile('.*?package (.*?);')
+  matches = re.findall(re_package, contents)
+  if not matches:
+    raise SyntaxError('Unable to find "package" line in %s' % java_file_name)
+  return (matches[0].replace('.', '/') + '/' +
+          os.path.splitext(os.path.basename(java_file_name))[0])
+
+
+def ExtractNatives(contents):
+  """Returns a list of dict containing information about a native method."""
+  contents = contents.replace('\n', '')
+  natives = []
+  re_native = re.compile(r'(@NativeClassQualifiedName'
+                         '\(\"(?P<native_class_name>.*?)\"\))?\s*'
+                         '(@NativeCall(\(\"(?P<java_class_name>.*?)\"\)))?\s*'
+                         '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*?native '
+                         '(?P<return>\S*?) '
+                         '(?P<name>\w+?)\((?P<params>.*?)\);')
+  for match in re.finditer(re_native, contents):
+    native = NativeMethod(
+        static='static' in match.group('qualifiers'),
+        java_class_name=match.group('java_class_name'),
+        native_class_name=match.group('native_class_name'),
+        return_type=match.group('return'),
+        name=match.group('name').replace('native', ''),
+        params=JniParams.Parse(match.group('params')))
+    natives += [native]
+  return natives
+
+
+def GetStaticCastForReturnType(return_type):
+  if return_type in ['String', 'java/lang/String']:
+    return 'jstring'
+  elif return_type.endswith('[]'):
+    return 'jobjectArray'
+  return None
+
+
+def GetEnvCall(is_constructor, is_static, return_type):
+  """Maps the types availabe via env->Call__Method."""
+  if is_constructor:
+    return 'NewObject'
+  env_call_map = {'boolean': 'Boolean',
+                  'byte': 'Byte',
+                  'char': 'Char',
+                  'short': 'Short',
+                  'int': 'Int',
+                  'long': 'Long',
+                  'float': 'Float',
+                  'void': 'Void',
+                  'double': 'Double',
+                  'Object': 'Object',
+                 }
+  call = env_call_map.get(return_type, 'Object')
+  if is_static:
+    call = 'Static' + call
+  return 'Call' + call + 'Method'
+
+
+def GetMangledParam(datatype):
+  """Returns a mangled identifier for the datatype."""
+  if len(datatype) <= 2:
+    return datatype.replace('[', 'A')
+  ret = ''
+  for i in range(1, len(datatype)):
+    c = datatype[i]
+    if c == '[':
+      ret += 'A'
+    elif c.isupper() or datatype[i - 1] in ['/', 'L']:
+      ret += c.upper()
+  return ret
+
+
+def GetMangledMethodName(name, params, return_type):
+  """Returns a mangled method name for the given signature.
+
+     The returned name can be used as a C identifier and will be unique for all
+     valid overloads of the same method.
+
+  Args:
+     name: string.
+     params: list of Param.
+     return_type: string.
+
+  Returns:
+      A mangled name.
+  """
+  mangled_items = []
+  for datatype in [return_type] + [x.datatype for x in params]:
+    mangled_items += [GetMangledParam(JniParams.JavaToJni(datatype))]
+  mangled_name = name + '_'.join(mangled_items)
+  assert re.match(r'[0-9a-zA-Z_]+', mangled_name)
+  return mangled_name
+
+
+def MangleCalledByNatives(called_by_natives):
+  """Mangles all the overloads from the call_by_natives list."""
+  method_counts = collections.defaultdict(
+      lambda: collections.defaultdict(lambda: 0))
+  for called_by_native in called_by_natives:
+    java_class_name = called_by_native.java_class_name
+    name = called_by_native.name
+    method_counts[java_class_name][name] += 1
+  for called_by_native in called_by_natives:
+    java_class_name = called_by_native.java_class_name
+    method_name = called_by_native.name
+    method_id_var_name = method_name
+    if method_counts[java_class_name][method_name] > 1:
+      method_id_var_name = GetMangledMethodName(method_name,
+                                                called_by_native.params,
+                                                called_by_native.return_type)
+    called_by_native.method_id_var_name = method_id_var_name
+  return called_by_natives
+
+
+# Regex to match the JNI return types that should be included in a
+# ScopedJavaLocalRef.
+RE_SCOPED_JNI_RETURN_TYPES = re.compile('jobject|jclass|jstring|.*Array')
+
+# Regex to match a string like "@CalledByNative public void foo(int bar)".
+RE_CALLED_BY_NATIVE = re.compile(
+    '@CalledByNative(?P<Unchecked>(Unchecked)*?)(?:\("(?P<annotation>.*)"\))?'
+    '\s+(?P<prefix>[\w ]*?)'
+    '\s*(?P<return_type>\w+)'
+    '\s+(?P<name>\w+)'
+    '\s*\((?P<params>[^\)]*)\)')
+
+
+def ExtractCalledByNatives(contents):
+  """Parses all methods annotated with @CalledByNative.
+
+  Args:
+    contents: the contents of the java file.
+
+  Returns:
+    A list of dict with information about the annotated methods.
+    TODO(bulach): return a CalledByNative object.
+
+  Raises:
+    ParseError: if unable to parse.
+  """
+  called_by_natives = []
+  for match in re.finditer(RE_CALLED_BY_NATIVE, contents):
+    called_by_natives += [CalledByNative(
+        system_class=False,
+        unchecked='Unchecked' in match.group('Unchecked'),
+        static='static' in match.group('prefix'),
+        java_class_name=match.group('annotation') or '',
+        return_type=match.group('return_type'),
+        name=match.group('name'),
+        params=JniParams.Parse(match.group('params')))]
+  # Check for any @CalledByNative occurrences that weren't matched.
+  unmatched_lines = re.sub(RE_CALLED_BY_NATIVE, '', contents).split('\n')
+  for line1, line2 in zip(unmatched_lines, unmatched_lines[1:]):
+    if '@CalledByNative' in line1:
+      raise ParseError('could not parse @CalledByNative method signature',
+                       line1, line2)
+  return MangleCalledByNatives(called_by_natives)
+
+
+class JNIFromJavaP(object):
+  """Uses 'javap' to parse a .class file and generate the JNI header file."""
+
+  def __init__(self, contents, namespace):
+    self.contents = contents
+    self.namespace = namespace
+    self.fully_qualified_class = re.match('.*?class (?P<class_name>.*?) ',
+                                          contents[1]).group('class_name')
+    self.fully_qualified_class = self.fully_qualified_class.replace('.', '/')
+    JniParams.SetFullyQualifiedClass(self.fully_qualified_class)
+    self.java_class_name = self.fully_qualified_class.split('/')[-1]
+    if not self.namespace:
+      self.namespace = 'JNI_' + self.java_class_name
+    re_method = re.compile('(?P<prefix>.*?)(?P<return_type>\S+?) (?P<name>\w+?)'
+                           '\((?P<params>.*?)\)')
+    self.called_by_natives = []
+    for content in contents[2:]:
+      match = re.match(re_method, content)
+      if not match:
+        continue
+      self.called_by_natives += [CalledByNative(
+          system_class=True,
+          unchecked=False,
+          static='static' in match.group('prefix'),
+          java_class_name='',
+          return_type=match.group('return_type').replace('.', '/'),
+          name=match.group('name'),
+          params=JniParams.Parse(match.group('params').replace('.', '/')))]
+    re_constructor = re.compile('.*? public ' +
+                                self.fully_qualified_class.replace('/', '.') +
+                                '\((?P<params>.*?)\)')
+    for content in contents[2:]:
+      match = re.match(re_constructor, content)
+      if not match:
+        continue
+      self.called_by_natives += [CalledByNative(
+          system_class=True,
+          unchecked=False,
+          static=False,
+          java_class_name='',
+          return_type=self.fully_qualified_class,
+          name='Constructor',
+          params=JniParams.Parse(match.group('params').replace('.', '/')),
+          is_constructor=True)]
+    self.called_by_natives = MangleCalledByNatives(self.called_by_natives)
+    self.inl_header_file_generator = InlHeaderFileGenerator(
+        self.namespace, self.fully_qualified_class, [], self.called_by_natives)
+
+  def GetContent(self):
+    return self.inl_header_file_generator.GetContent()
+
+  @staticmethod
+  def CreateFromClass(class_file, namespace):
+    class_name = os.path.splitext(os.path.basename(class_file))[0]
+    p = subprocess.Popen(args=['javap', class_name],
+                         cwd=os.path.dirname(class_file),
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE)
+    stdout, _ = p.communicate()
+    jni_from_javap = JNIFromJavaP(stdout.split('\n'), namespace)
+    return jni_from_javap
+
+
+class JNIFromJavaSource(object):
+  """Uses the given java source file to generate the JNI header file."""
+
+  def __init__(self, contents, fully_qualified_class):
+    contents = self._RemoveComments(contents)
+    JniParams.SetFullyQualifiedClass(fully_qualified_class)
+    JniParams.ExtractImportsAndInnerClasses(contents)
+    jni_namespace = ExtractJNINamespace(contents)
+    natives = ExtractNatives(contents)
+    called_by_natives = ExtractCalledByNatives(contents)
+    if len(natives) == 0 and len(called_by_natives) == 0:
+      raise SyntaxError('Unable to find any JNI methods for %s.' %
+                        fully_qualified_class)
+    inl_header_file_generator = InlHeaderFileGenerator(
+        jni_namespace, fully_qualified_class, natives, called_by_natives)
+    self.content = inl_header_file_generator.GetContent()
+
+  def _RemoveComments(self, contents):
+    # We need to support both inline and block comments, and we need to handle
+    # strings that contain '//' or '/*'. Rather than trying to do all that with
+    # regexps, we just pipe the contents through the C preprocessor. We tell cpp
+    # the file has already been preprocessed, so it just removes comments and
+    # doesn't try to parse #include, #pragma etc.
+    #
+    # TODO(husky): This is a bit hacky. It would be cleaner to use a real Java
+    # parser. Maybe we could ditch JNIFromJavaSource and just always use
+    # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT.
+    # http://code.google.com/p/chromium/issues/detail?id=138941
+    p = subprocess.Popen(args=['cpp', '-fpreprocessed'],
+                         stdin=subprocess.PIPE,
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE)
+    stdout, _ = p.communicate(contents)
+    return stdout
+
+  def GetContent(self):
+    return self.content
+
+  @staticmethod
+  def CreateFromFile(java_file_name):
+    contents = file(java_file_name).read()
+    fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name,
+                                                               contents)
+    return JNIFromJavaSource(contents, fully_qualified_class)
+
+
+class InlHeaderFileGenerator(object):
+  """Generates an inline header file for JNI integration."""
+
+  def __init__(self, namespace, fully_qualified_class, natives,
+               called_by_natives):
+    self.namespace = namespace
+    self.fully_qualified_class = fully_qualified_class
+    self.class_name = self.fully_qualified_class.split('/')[-1]
+    self.natives = natives
+    self.called_by_natives = called_by_natives
+    self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI'
+
+  def GetContent(self):
+    """Returns the content of the JNI binding file."""
+    template = Template("""\
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+// This file is autogenerated by
+//     ${SCRIPT_NAME}
+// For
+//     ${FULLY_QUALIFIED_CLASS}
+
+#ifndef ${HEADER_GUARD}
+#define ${HEADER_GUARD}
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+$CLASS_PATH_DEFINITIONS
+}  // namespace
+
+$OPEN_NAMESPACE
+$FORWARD_DECLARATIONS
+
+// Step 2: method stubs.
+$METHOD_STUBS
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+$REGISTER_NATIVES_IMPL
+  return true;
+}
+$CLOSE_NAMESPACE
+#endif  // ${HEADER_GUARD}
+""")
+    script_components = os.path.abspath(sys.argv[0]).split(os.path.sep)
+    base_index = script_components.index('base')
+    script_name = os.sep.join(script_components[base_index:])
+    values = {
+        'SCRIPT_NAME': script_name,
+        'FULLY_QUALIFIED_CLASS': self.fully_qualified_class,
+        'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(),
+        'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(),
+        'METHOD_STUBS': self.GetMethodStubsString(),
+        'OPEN_NAMESPACE': self.GetOpenNamespaceString(),
+        'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(),
+        'CLOSE_NAMESPACE': self.GetCloseNamespaceString(),
+        'HEADER_GUARD': self.header_guard,
+    }
+    return WrapOutput(template.substitute(values))
+
+  def GetClassPathDefinitionsString(self):
+    ret = []
+    ret += [self.GetClassPathDefinitions()]
+    return '\n'.join(ret)
+
+  def GetForwardDeclarationsString(self):
+    ret = []
+    for native in self.natives:
+      if native.type != 'method':
+        ret += [self.GetForwardDeclaration(native)]
+    return '\n'.join(ret)
+
+  def GetMethodStubsString(self):
+    ret = []
+    for native in self.natives:
+      if native.type == 'method':
+        ret += [self.GetNativeMethodStub(native)]
+    for called_by_native in self.called_by_natives:
+      ret += [self.GetCalledByNativeMethodStub(called_by_native)]
+    return '\n'.join(ret)
+
+  def GetKMethodsString(self, clazz):
+    ret = []
+    for native in self.natives:
+      if (native.java_class_name == clazz or
+          (not native.java_class_name and clazz == self.class_name)):
+        ret += [self.GetKMethodArrayEntry(native)]
+    return '\n'.join(ret)
+
+  def GetRegisterNativesImplString(self):
+    """Returns the implementation for RegisterNatives."""
+    template = Template("""\
+  static const JNINativeMethod kMethods${JAVA_CLASS}[] = {
+${KMETHODS}
+  };
+  const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS});
+
+  if (env->RegisterNatives(g_${JAVA_CLASS}_clazz,
+                           kMethods${JAVA_CLASS},
+                           kMethods${JAVA_CLASS}Size) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+""")
+    ret = [self.GetFindClasses()]
+    all_classes = self.GetUniqueClasses(self.natives)
+    all_classes[self.class_name] = self.fully_qualified_class
+    for clazz in all_classes:
+      kmethods = self.GetKMethodsString(clazz)
+      if kmethods:
+        values = {'JAVA_CLASS': clazz,
+                  'KMETHODS': kmethods}
+        ret += [template.substitute(values)]
+    if not ret: return ''
+    return '\n' + '\n'.join(ret)
+
+  def GetOpenNamespaceString(self):
+    if self.namespace:
+      all_namespaces = ['namespace %s {' % ns
+                        for ns in self.namespace.split('::')]
+      return '\n'.join(all_namespaces)
+    return ''
+
+  def GetCloseNamespaceString(self):
+    if self.namespace:
+      all_namespaces = ['}  // namespace %s' % ns
+                        for ns in self.namespace.split('::')]
+      all_namespaces.reverse()
+      return '\n'.join(all_namespaces) + '\n'
+    return ''
+
+  def GetJNIFirstParam(self, native):
+    ret = []
+    if native.type == 'method':
+      ret = ['jobject obj']
+    elif native.type == 'function':
+      if native.static:
+        ret = ['jclass clazz']
+      else:
+        ret = ['jobject obj']
+    return ret
+
+  def GetParamsInDeclaration(self, native):
+    """Returns the params for the stub declaration.
+
+    Args:
+      native: the native dictionary describing the method.
+
+    Returns:
+      A string containing the params.
+    """
+    return ',\n    '.join(self.GetJNIFirstParam(native) +
+                          [JavaDataTypeToC(param.datatype) + ' ' +
+                           param.name
+                           for param in native.params])
+
+  def GetCalledByNativeParamsInDeclaration(self, called_by_native):
+    return ',\n    '.join([JavaDataTypeToC(param.datatype) + ' ' +
+                           param.name
+                           for param in called_by_native.params])
+
+  def GetForwardDeclaration(self, native):
+    template = Template("""
+static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS});
+""")
+    values = {'RETURN': JavaDataTypeToC(native.return_type),
+              'NAME': native.name,
+              'PARAMS': self.GetParamsInDeclaration(native)}
+    return template.substitute(values)
+
+  def GetNativeMethodStub(self, native):
+    """Returns stubs for native methods."""
+    template = Template("""\
+static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) {
+  DCHECK(${PARAM0_NAME}) << "${NAME}";
+  ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME});
+  return native->${NAME}(env, obj${PARAMS_IN_CALL})${POST_CALL};
+}
+""")
+    params_for_call = ', '.join(p.name for p in native.params[1:])
+    if params_for_call:
+      params_for_call = ', ' + params_for_call
+
+    return_type = JavaDataTypeToC(native.return_type)
+    if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type):
+      scoped_return_type = 'ScopedJavaLocalRef<' + return_type + '>'
+      post_call = '.Release()'
+    else:
+      scoped_return_type = return_type
+      post_call = ''
+    values = {
+        'RETURN': return_type,
+        'SCOPED_RETURN': scoped_return_type,
+        'NAME': native.name,
+        'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native),
+        'PARAM0_NAME': native.params[0].name,
+        'P0_TYPE': native.p0_type,
+        'PARAMS_IN_CALL': params_for_call,
+        'POST_CALL': post_call
+    }
+    return template.substitute(values)
+
+  def GetCalledByNativeMethodStub(self, called_by_native):
+    """Returns a string."""
+    function_signature_template = Template("""\
+static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\
+JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""")
+    function_header_template = Template("""\
+${FUNCTION_SIGNATURE} {""")
+    function_header_with_unused_template = Template("""\
+${FUNCTION_SIGNATURE} __attribute__ ((unused));
+${FUNCTION_SIGNATURE} {""")
+    template = Template("""
+static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0;
+${FUNCTION_HEADER}
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_${JAVA_CLASS}_clazz);
+  jmethodID method_id =
+    ${GET_METHOD_ID_IMPL}
+  ${RETURN_DECLARATION}
+  ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL},
+      method_id${PARAMS_IN_CALL})${POST_CALL};
+  ${CHECK_EXCEPTION}
+  ${RETURN_CLAUSE}
+}""")
+    if called_by_native.static or called_by_native.is_constructor:
+      first_param_in_declaration = ''
+      first_param_in_call = ('g_%s_clazz' %
+                             (called_by_native.java_class_name or
+                              self.class_name))
+    else:
+      first_param_in_declaration = ', jobject obj'
+      first_param_in_call = 'obj'
+    params_in_declaration = self.GetCalledByNativeParamsInDeclaration(
+        called_by_native)
+    if params_in_declaration:
+      params_in_declaration = ', ' + params_in_declaration
+    params_for_call = ', '.join(param.name
+                                for param in called_by_native.params)
+    if params_for_call:
+      params_for_call = ', ' + params_for_call
+    pre_call = ''
+    post_call = ''
+    if called_by_native.static_cast:
+      pre_call = 'static_cast<%s>(' % called_by_native.static_cast
+      post_call = ')'
+    check_exception = ''
+    if not called_by_native.unchecked:
+      check_exception = 'base::android::CheckException(env);'
+    return_type = JavaDataTypeToC(called_by_native.return_type)
+    return_declaration = ''
+    return_clause = ''
+    if return_type != 'void':
+      pre_call = '  ' + pre_call
+      return_declaration = return_type + ' ret ='
+      if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type):
+        return_type = 'ScopedJavaLocalRef<' + return_type + '>'
+        return_clause = 'return ' + return_type + '(env, ret);'
+      else:
+        return_clause = 'return ret;'
+    values = {
+        'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
+        'METHOD': called_by_native.name,
+        'RETURN_TYPE': return_type,
+        'RETURN_DECLARATION': return_declaration,
+        'RETURN_CLAUSE': return_clause,
+        'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration,
+        'PARAMS_IN_DECLARATION': params_in_declaration,
+        'STATIC': 'Static' if called_by_native.static else '',
+        'PRE_CALL': pre_call,
+        'POST_CALL': post_call,
+        'ENV_CALL': called_by_native.env_call,
+        'FIRST_PARAM_IN_CALL': first_param_in_call,
+        'PARAMS_IN_CALL': params_for_call,
+        'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
+        'CHECK_EXCEPTION': check_exception,
+        'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native)
+    }
+    values['FUNCTION_SIGNATURE'] = (
+        function_signature_template.substitute(values))
+    if called_by_native.system_class:
+      values['FUNCTION_HEADER'] = (
+          function_header_with_unused_template.substitute(values))
+    else:
+      values['FUNCTION_HEADER'] = function_header_template.substitute(values)
+    return template.substitute(values)
+
+  def GetKMethodArrayEntry(self, native):
+    template = Template("""\
+    { "native${NAME}", ${JNI_SIGNATURE}, reinterpret_cast<void*>(${NAME}) },""")
+    values = {'NAME': native.name,
+              'JNI_SIGNATURE': JniParams.Signature(native.params,
+                                                   native.return_type,
+                                                   True)}
+    return template.substitute(values)
+
+  def GetUniqueClasses(self, origin):
+    ret = {self.class_name: self.fully_qualified_class}
+    for entry in origin:
+      class_name = self.class_name
+      jni_class_path = self.fully_qualified_class
+      if entry.java_class_name:
+        class_name = entry.java_class_name
+        jni_class_path = self.fully_qualified_class + '$' + class_name
+      ret[class_name] = jni_class_path
+    return ret
+
+  def GetClassPathDefinitions(self):
+    """Returns the ClassPath constants."""
+    ret = []
+    template = Template("""\
+const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""")
+    native_classes = self.GetUniqueClasses(self.natives)
+    called_by_native_classes = self.GetUniqueClasses(self.called_by_natives)
+    all_classes = native_classes
+    all_classes.update(called_by_native_classes)
+    for clazz in all_classes:
+      values = {
+          'JAVA_CLASS': clazz,
+          'JNI_CLASS_PATH': all_classes[clazz],
+      }
+      ret += [template.substitute(values)]
+    ret += ''
+    for clazz in called_by_native_classes:
+      template = Template("""\
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_${JAVA_CLASS}_clazz = NULL;""")
+      values = {
+          'JAVA_CLASS': clazz,
+      }
+      ret += [template.substitute(values)]
+    return '\n'.join(ret)
+
+  def GetFindClasses(self):
+    """Returns the imlementation of FindClass for all known classes."""
+    template = Template("""\
+  g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, k${JAVA_CLASS}ClassPath)));""")
+    ret = []
+    for clazz in self.GetUniqueClasses(self.called_by_natives):
+      values = {'JAVA_CLASS': clazz}
+      ret += [template.substitute(values)]
+    return '\n'.join(ret)
+
+  def GetMethodIDImpl(self, called_by_native):
+    """Returns the implementation of GetMethodID."""
+    template = Template("""\
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_${STATIC}>(
+      env, g_${JAVA_CLASS}_clazz,
+      "${JNI_NAME}",
+      ${JNI_SIGNATURE},
+      &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME});
+""")
+    jni_name = called_by_native.name
+    jni_return_type = called_by_native.return_type
+    if called_by_native.is_constructor:
+      jni_name = '<init>'
+      jni_return_type = 'void'
+    values = {
+        'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
+        'JNI_NAME': jni_name,
+        'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
+        'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE',
+        'JNI_SIGNATURE': JniParams.Signature(called_by_native.params,
+                                             jni_return_type,
+                                             True)
+    }
+    return template.substitute(values)
+
+
+def WrapOutput(output):
+  ret = []
+  for line in output.splitlines():
+    # Do not wrap lines under 80 characters or preprocessor directives.
+    if len(line) < 80 or line.lstrip()[:1] == '#':
+      stripped = line.rstrip()
+      if len(ret) == 0 or len(ret[-1]) or len(stripped):
+        ret.append(stripped)
+    else:
+      first_line_indent = ' ' * (len(line) - len(line.lstrip()))
+      subsequent_indent =  first_line_indent + ' ' * 4
+      if line.startswith('//'):
+        subsequent_indent = '//' + subsequent_indent
+      wrapper = textwrap.TextWrapper(width=80,
+                                     subsequent_indent=subsequent_indent,
+                                     break_long_words=False)
+      ret += [wrapped.rstrip() for wrapped in wrapper.wrap(line)]
+  ret += ['']
+  return '\n'.join(ret)
+
+
+def ExtractJarInputFile(jar_file, input_file, out_dir):
+  """Extracts input file from jar and returns the filename.
+
+  The input file is extracted to the same directory that the generated jni
+  headers will be placed in.  This is passed as an argument to script.
+
+  Args:
+    jar_file: the jar file containing the input files to extract.
+    input_files: the list of files to extract from the jar file.
+    out_dir: the name of the directories to extract to.
+
+  Returns:
+    the name of extracted input file.
+  """
+  jar_file = zipfile.ZipFile(jar_file)
+
+  out_dir = os.path.join(out_dir, os.path.dirname(input_file))
+  if not os.path.exists(out_dir):
+    os.makedirs(out_dir)
+  extracted_file_name = os.path.join(out_dir, os.path.basename(input_file))
+  with open(extracted_file_name, 'w') as outfile:
+    outfile.write(jar_file.read(input_file))
+
+  return extracted_file_name
+
+
+def GenerateJNIHeader(input_file, output_file, namespace):
+  try:
+    if os.path.splitext(input_file)[1] == '.class':
+      jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, namespace)
+      content = jni_from_javap.GetContent()
+    else:
+      jni_from_java_source = JNIFromJavaSource.CreateFromFile(input_file)
+      content = jni_from_java_source.GetContent()
+  except ParseError, e:
+    print e
+    sys.exit(1)
+  if output_file:
+    if not os.path.exists(os.path.dirname(os.path.abspath(output_file))):
+      os.makedirs(os.path.dirname(os.path.abspath(output_file)))
+    with file(output_file, 'w') as f:
+      f.write(content)
+  else:
+    print output
+
+
+def main(argv):
+  usage = """usage: %prog [OPTIONS]
+This script will parse the given java source code extracting the native
+declarations and print the header file to stdout (or a file).
+See SampleForTests.java for more details.
+  """
+  option_parser = optparse.OptionParser(usage=usage)
+  option_parser.add_option('-j', dest='jar_file',
+                           help='Extract the list of input files from'
+                           ' a specified jar file.'
+                           ' Uses javap to extract the methods from a'
+                           ' pre-compiled class. --input should point'
+                           ' to pre-compiled Java .class files.')
+  option_parser.add_option('-n', dest='namespace',
+                           help='Uses as a namespace in the generated header,'
+                           ' instead of the javap class name.')
+  option_parser.add_option('--input_file',
+                           help='Single input file name. The output file name '
+                           'will be derived from it. Must be used with '
+                           '--output_dir.')
+  option_parser.add_option('--output_dir',
+                           help='The output directory. Must be used with '
+                           '--input')
+  options, args = option_parser.parse_args(argv)
+  if options.jar_file:
+    input_file = ExtractJarInputFile(options.jar_file, options.input_file,
+                                     options.output_dir)
+  else:
+    input_file = options.input_file
+  output_file = None
+  if options.output_dir:
+    root_name = os.path.splitext(os.path.basename(input_file))[0]
+    output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
+  GenerateJNIHeader(input_file, output_file, options.namespace)
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/src/base/android/jni_generator/jni_generator_tests.py b/src/base/android/jni_generator/jni_generator_tests.py
new file mode 100755
index 0000000..5863977
--- /dev/null
+++ b/src/base/android/jni_generator/jni_generator_tests.py
@@ -0,0 +1,1590 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for jni_generator.py.
+
+This test suite contains various tests for the JNI generator.
+It exercises the low-level parser all the way up to the
+code generator and ensures the output matches a golden
+file.
+"""
+
+import difflib
+import os
+import sys
+import unittest
+import jni_generator
+from jni_generator import CalledByNative, NativeMethod, Param
+
+
+class TestGenerator(unittest.TestCase):
+  def assertObjEquals(self, first, second):
+    dict_first = first.__dict__
+    dict_second = second.__dict__
+    self.assertEquals(dict_first.keys(), dict_second.keys())
+    for key, value in dict_first.iteritems():
+      if (type(value) is list and len(value) and
+          isinstance(type(value[0]), object)):
+        self.assertListEquals(value, second.__getattribute__(key))
+      else:
+        actual = second.__getattribute__(key)
+        self.assertEquals(value, actual,
+                          'Key ' + key + ': ' + str(value) + '!=' + str(actual))
+
+  def assertListEquals(self, first, second):
+    self.assertEquals(len(first), len(second))
+    for i in xrange(len(first)):
+      if isinstance(first[i], object):
+        self.assertObjEquals(first[i], second[i])
+      else:
+        self.assertEquals(first[i], second[i])
+
+  def assertTextEquals(self, golden_text, generated_text):
+    stripped_golden = [l.strip() for l in golden_text.split('\n')]
+    stripped_generated = [l.strip() for l in generated_text.split('\n')]
+    if stripped_golden != stripped_generated:
+      print self.id()
+      for line in difflib.context_diff(stripped_golden, stripped_generated):
+        print line
+      print '\n\nGenerated'
+      print '=' * 80
+      print generated_text
+      print '=' * 80
+      self.fail('Golden text mismatch')
+
+  def testNatives(self):
+    test_data = """"
+    interface OnFrameAvailableListener {}
+    private native int nativeInit();
+    private native void nativeDestroy(int nativeChromeBrowserProvider);
+    private native long nativeAddBookmark(
+            int nativeChromeBrowserProvider,
+            String url, String title, boolean isFolder, long parentId);
+    private static native String nativeGetDomainAndRegistry(String url);
+    private static native void nativeCreateHistoricalTabFromState(
+            byte[] state, int tab_index);
+    private native byte[] nativeGetStateAsByteArray(View view);
+    private static native String[] nativeGetAutofillProfileGUIDs();
+    private native void nativeSetRecognitionResults(
+            int sessionId, String[] results);
+    private native long nativeAddBookmarkFromAPI(
+            int nativeChromeBrowserProvider,
+            String url, Long created, Boolean isBookmark,
+            Long date, byte[] favicon, String title, Integer visits);
+    native int nativeFindAll(String find);
+    private static native OnFrameAvailableListener nativeGetInnerClass();
+    private native Bitmap nativeQueryBitmap(
+            int nativeChromeBrowserProvider,
+            String[] projection, String selection,
+            String[] selectionArgs, String sortOrder);
+    private native void nativeGotOrientation(
+            int nativeDataFetcherImplAndroid,
+            double alpha, double beta, double gamma);
+    """
+    jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
+    natives = jni_generator.ExtractNatives(test_data)
+    golden_natives = [
+        NativeMethod(return_type='int', static=False,
+                     name='Init',
+                     params=[],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='void', static=False, name='Destroy',
+                     params=[Param(datatype='int',
+                                   name='nativeChromeBrowserProvider')],
+                     java_class_name=None,
+                     type='method',
+                     p0_type='ChromeBrowserProvider'),
+        NativeMethod(return_type='long', static=False, name='AddBookmark',
+                     params=[Param(datatype='int',
+                                   name='nativeChromeBrowserProvider'),
+                             Param(datatype='String',
+                                   name='url'),
+                             Param(datatype='String',
+                                   name='title'),
+                             Param(datatype='boolean',
+                                   name='isFolder'),
+                             Param(datatype='long',
+                                   name='parentId')],
+                     java_class_name=None,
+                     type='method',
+                     p0_type='ChromeBrowserProvider'),
+        NativeMethod(return_type='String', static=True,
+                     name='GetDomainAndRegistry',
+                     params=[Param(datatype='String',
+                                   name='url')],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='void', static=True,
+                     name='CreateHistoricalTabFromState',
+                     params=[Param(datatype='byte[]',
+                                   name='state'),
+                             Param(datatype='int',
+                                   name='tab_index')],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='byte[]', static=False,
+                     name='GetStateAsByteArray',
+                     params=[Param(datatype='View', name='view')],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='String[]', static=True,
+                     name='GetAutofillProfileGUIDs', params=[],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='void', static=False,
+                     name='SetRecognitionResults',
+                     params=[Param(datatype='int', name='sessionId'),
+                             Param(datatype='String[]', name='results')],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='long', static=False,
+                     name='AddBookmarkFromAPI',
+                     params=[Param(datatype='int',
+                                   name='nativeChromeBrowserProvider'),
+                             Param(datatype='String',
+                                   name='url'),
+                             Param(datatype='Long',
+                                   name='created'),
+                             Param(datatype='Boolean',
+                                   name='isBookmark'),
+                             Param(datatype='Long',
+                                   name='date'),
+                             Param(datatype='byte[]',
+                                   name='favicon'),
+                             Param(datatype='String',
+                                   name='title'),
+                             Param(datatype='Integer',
+                                   name='visits')],
+                     java_class_name=None,
+                     type='method',
+                     p0_type='ChromeBrowserProvider'),
+        NativeMethod(return_type='int', static=False,
+                     name='FindAll',
+                     params=[Param(datatype='String',
+                                   name='find')],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='OnFrameAvailableListener', static=True,
+                     name='GetInnerClass',
+                     params=[],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='Bitmap',
+                     static=False,
+                     name='QueryBitmap',
+                     params=[Param(datatype='int',
+                                   name='nativeChromeBrowserProvider'),
+                             Param(datatype='String[]',
+                                   name='projection'),
+                             Param(datatype='String',
+                                   name='selection'),
+                             Param(datatype='String[]',
+                                   name='selectionArgs'),
+                             Param(datatype='String',
+                                   name='sortOrder'),
+                            ],
+                     java_class_name=None,
+                     type='method',
+                     p0_type='ChromeBrowserProvider'),
+        NativeMethod(return_type='void', static=False,
+                     name='GotOrientation',
+                     params=[Param(datatype='int',
+                                   name='nativeDataFetcherImplAndroid'),
+                             Param(datatype='double',
+                                   name='alpha'),
+                             Param(datatype='double',
+                                   name='beta'),
+                             Param(datatype='double',
+                                   name='gamma'),
+                            ],
+                     java_class_name=None,
+                     type='method',
+                     p0_type='content::DataFetcherImplAndroid'),
+    ]
+    self.assertListEquals(golden_natives, natives)
+    h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
+                                             natives, [])
+    golden_content = """\
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     base/android/jni_generator/jni_generator_tests.py
+// For
+//     org/chromium/TestJni
+
+#ifndef org_chromium_TestJni_JNI
+#define org_chromium_TestJni_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kTestJniClassPath[] = "org/chromium/TestJni";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_TestJni_clazz = NULL;
+}  // namespace
+
+static jint Init(JNIEnv* env, jobject obj);
+
+static jstring GetDomainAndRegistry(JNIEnv* env, jclass clazz,
+    jstring url);
+
+static void CreateHistoricalTabFromState(JNIEnv* env, jclass clazz,
+    jbyteArray state,
+    jint tab_index);
+
+static jbyteArray GetStateAsByteArray(JNIEnv* env, jobject obj,
+    jobject view);
+
+static jobjectArray GetAutofillProfileGUIDs(JNIEnv* env, jclass clazz);
+
+static void SetRecognitionResults(JNIEnv* env, jobject obj,
+    jint sessionId,
+    jobjectArray results);
+
+static jint FindAll(JNIEnv* env, jobject obj,
+    jstring find);
+
+static jobject GetInnerClass(JNIEnv* env, jclass clazz);
+
+// Step 2: method stubs.
+static void Destroy(JNIEnv* env, jobject obj,
+    jint nativeChromeBrowserProvider) {
+  DCHECK(nativeChromeBrowserProvider) << "Destroy";
+  ChromeBrowserProvider* native =
+      reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
+  return native->Destroy(env, obj);
+}
+
+static jlong AddBookmark(JNIEnv* env, jobject obj,
+    jint nativeChromeBrowserProvider,
+    jstring url,
+    jstring title,
+    jboolean isFolder,
+    jlong parentId) {
+  DCHECK(nativeChromeBrowserProvider) << "AddBookmark";
+  ChromeBrowserProvider* native =
+      reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
+  return native->AddBookmark(env, obj, url, title, isFolder, parentId);
+}
+
+static jlong AddBookmarkFromAPI(JNIEnv* env, jobject obj,
+    jint nativeChromeBrowserProvider,
+    jstring url,
+    jobject created,
+    jobject isBookmark,
+    jobject date,
+    jbyteArray favicon,
+    jstring title,
+    jobject visits) {
+  DCHECK(nativeChromeBrowserProvider) << "AddBookmarkFromAPI";
+  ChromeBrowserProvider* native =
+      reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
+  return native->AddBookmarkFromAPI(env, obj, url, created, isBookmark, date,
+      favicon, title, visits);
+}
+
+static jobject QueryBitmap(JNIEnv* env, jobject obj,
+    jint nativeChromeBrowserProvider,
+    jobjectArray projection,
+    jstring selection,
+    jobjectArray selectionArgs,
+    jstring sortOrder) {
+  DCHECK(nativeChromeBrowserProvider) << "QueryBitmap";
+  ChromeBrowserProvider* native =
+      reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
+  return native->QueryBitmap(env, obj, projection, selection, selectionArgs,
+      sortOrder).Release();
+}
+
+static void GotOrientation(JNIEnv* env, jobject obj,
+    jint nativeDataFetcherImplAndroid,
+    jdouble alpha,
+    jdouble beta,
+    jdouble gamma) {
+  DCHECK(nativeDataFetcherImplAndroid) << "GotOrientation";
+  DataFetcherImplAndroid* native =
+      reinterpret_cast<DataFetcherImplAndroid*>(nativeDataFetcherImplAndroid);
+  return native->GotOrientation(env, obj, alpha, beta, gamma);
+}
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kTestJniClassPath)));
+  static const JNINativeMethod kMethodsTestJni[] = {
+    { "nativeInit",
+"("
+")"
+"I", reinterpret_cast<void*>(Init) },
+    { "nativeDestroy",
+"("
+"I"
+")"
+"V", reinterpret_cast<void*>(Destroy) },
+    { "nativeAddBookmark",
+"("
+"I"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+"Z"
+"J"
+")"
+"J", reinterpret_cast<void*>(AddBookmark) },
+    { "nativeGetDomainAndRegistry",
+"("
+"Ljava/lang/String;"
+")"
+"Ljava/lang/String;", reinterpret_cast<void*>(GetDomainAndRegistry) },
+    { "nativeCreateHistoricalTabFromState",
+"("
+"[B"
+"I"
+")"
+"V", reinterpret_cast<void*>(CreateHistoricalTabFromState) },
+    { "nativeGetStateAsByteArray",
+"("
+"Landroid/view/View;"
+")"
+"[B", reinterpret_cast<void*>(GetStateAsByteArray) },
+    { "nativeGetAutofillProfileGUIDs",
+"("
+")"
+"[Ljava/lang/String;", reinterpret_cast<void*>(GetAutofillProfileGUIDs) },
+    { "nativeSetRecognitionResults",
+"("
+"I"
+"[Ljava/lang/String;"
+")"
+"V", reinterpret_cast<void*>(SetRecognitionResults) },
+    { "nativeAddBookmarkFromAPI",
+"("
+"I"
+"Ljava/lang/String;"
+"Ljava/lang/Long;"
+"Ljava/lang/Boolean;"
+"Ljava/lang/Long;"
+"[B"
+"Ljava/lang/String;"
+"Ljava/lang/Integer;"
+")"
+"J", reinterpret_cast<void*>(AddBookmarkFromAPI) },
+    { "nativeFindAll",
+"("
+"Ljava/lang/String;"
+")"
+"I", reinterpret_cast<void*>(FindAll) },
+    { "nativeGetInnerClass",
+"("
+")"
+"Lorg/chromium/example/jni_generator/SampleForTests$OnFrameAvailableListener;",
+    reinterpret_cast<void*>(GetInnerClass) },
+    { "nativeQueryBitmap",
+"("
+"I"
+"[Ljava/lang/String;"
+"Ljava/lang/String;"
+"[Ljava/lang/String;"
+"Ljava/lang/String;"
+")"
+"Landroid/graphics/Bitmap;", reinterpret_cast<void*>(QueryBitmap) },
+    { "nativeGotOrientation",
+"("
+"I"
+"D"
+"D"
+"D"
+")"
+"V", reinterpret_cast<void*>(GotOrientation) },
+  };
+  const int kMethodsTestJniSize = arraysize(kMethodsTestJni);
+
+  if (env->RegisterNatives(g_TestJni_clazz,
+                           kMethodsTestJni,
+                           kMethodsTestJniSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  return true;
+}
+
+#endif  // org_chromium_TestJni_JNI
+"""
+    self.assertTextEquals(golden_content, h.GetContent())
+
+  def testInnerClassNatives(self):
+    test_data = """
+    class MyInnerClass {
+      @NativeCall("MyInnerClass")
+      private native int nativeInit();
+    }
+    """
+    natives = jni_generator.ExtractNatives(test_data)
+    golden_natives = [
+        NativeMethod(return_type='int', static=False,
+                     name='Init', params=[],
+                     java_class_name='MyInnerClass',
+                     type='function')
+    ]
+    self.assertListEquals(golden_natives, natives)
+    h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
+                                             natives, [])
+    golden_content = """\
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     base/android/jni_generator/jni_generator_tests.py
+// For
+//     org/chromium/TestJni
+
+#ifndef org_chromium_TestJni_JNI
+#define org_chromium_TestJni_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kTestJniClassPath[] = "org/chromium/TestJni";
+const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_TestJni_clazz = NULL;
+}  // namespace
+
+static jint Init(JNIEnv* env, jobject obj);
+
+// Step 2: method stubs.
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kTestJniClassPath)));
+  static const JNINativeMethod kMethodsMyInnerClass[] = {
+    { "nativeInit",
+"("
+")"
+"I", reinterpret_cast<void*>(Init) },
+  };
+  const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass);
+
+  if (env->RegisterNatives(g_MyInnerClass_clazz,
+                           kMethodsMyInnerClass,
+                           kMethodsMyInnerClassSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  return true;
+}
+
+#endif  // org_chromium_TestJni_JNI
+"""
+    self.assertTextEquals(golden_content, h.GetContent())
+
+  def testInnerClassNativesMultiple(self):
+    test_data = """
+    class MyInnerClass {
+      @NativeCall("MyInnerClass")
+      private native int nativeInit();
+    }
+    class MyOtherInnerClass {
+      @NativeCall("MyOtherInnerClass")
+      private native int nativeInit();
+    }
+    """
+    natives = jni_generator.ExtractNatives(test_data)
+    golden_natives = [
+        NativeMethod(return_type='int', static=False,
+                     name='Init', params=[],
+                     java_class_name='MyInnerClass',
+                     type='function'),
+        NativeMethod(return_type='int', static=False,
+                     name='Init', params=[],
+                     java_class_name='MyOtherInnerClass',
+                     type='function')
+    ]
+    self.assertListEquals(golden_natives, natives)
+    h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
+                                             natives, [])
+    golden_content = """\
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     base/android/jni_generator/jni_generator_tests.py
+// For
+//     org/chromium/TestJni
+
+#ifndef org_chromium_TestJni_JNI
+#define org_chromium_TestJni_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kMyOtherInnerClassClassPath[] =
+    "org/chromium/TestJni$MyOtherInnerClass";
+const char kTestJniClassPath[] = "org/chromium/TestJni";
+const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_TestJni_clazz = NULL;
+}  // namespace
+
+static jint Init(JNIEnv* env, jobject obj);
+
+static jint Init(JNIEnv* env, jobject obj);
+
+// Step 2: method stubs.
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kTestJniClassPath)));
+  static const JNINativeMethod kMethodsMyOtherInnerClass[] = {
+    { "nativeInit",
+"("
+")"
+"I", reinterpret_cast<void*>(Init) },
+  };
+  const int kMethodsMyOtherInnerClassSize =
+      arraysize(kMethodsMyOtherInnerClass);
+
+  if (env->RegisterNatives(g_MyOtherInnerClass_clazz,
+                           kMethodsMyOtherInnerClass,
+                           kMethodsMyOtherInnerClassSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  static const JNINativeMethod kMethodsMyInnerClass[] = {
+    { "nativeInit",
+"("
+")"
+"I", reinterpret_cast<void*>(Init) },
+  };
+  const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass);
+
+  if (env->RegisterNatives(g_MyInnerClass_clazz,
+                           kMethodsMyInnerClass,
+                           kMethodsMyInnerClassSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  return true;
+}
+
+#endif  // org_chromium_TestJni_JNI
+"""
+    self.assertTextEquals(golden_content, h.GetContent())
+
+  def testInnerClassNativesBothInnerAndOuter(self):
+    test_data = """
+    class MyOuterClass {
+      private native int nativeInit();
+      class MyOtherInnerClass {
+        @NativeCall("MyOtherInnerClass")
+        private native int nativeInit();
+      }
+    }
+    """
+    natives = jni_generator.ExtractNatives(test_data)
+    golden_natives = [
+        NativeMethod(return_type='int', static=False,
+                     name='Init', params=[],
+                     java_class_name=None,
+                     type='function'),
+        NativeMethod(return_type='int', static=False,
+                     name='Init', params=[],
+                     java_class_name='MyOtherInnerClass',
+                     type='function')
+    ]
+    self.assertListEquals(golden_natives, natives)
+    h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
+                                             natives, [])
+    golden_content = """\
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     base/android/jni_generator/jni_generator_tests.py
+// For
+//     org/chromium/TestJni
+
+#ifndef org_chromium_TestJni_JNI
+#define org_chromium_TestJni_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kMyOtherInnerClassClassPath[] =
+    "org/chromium/TestJni$MyOtherInnerClass";
+const char kTestJniClassPath[] = "org/chromium/TestJni";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_TestJni_clazz = NULL;
+}  // namespace
+
+static jint Init(JNIEnv* env, jobject obj);
+
+static jint Init(JNIEnv* env, jobject obj);
+
+// Step 2: method stubs.
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kTestJniClassPath)));
+  static const JNINativeMethod kMethodsMyOtherInnerClass[] = {
+    { "nativeInit",
+"("
+")"
+"I", reinterpret_cast<void*>(Init) },
+  };
+  const int kMethodsMyOtherInnerClassSize =
+      arraysize(kMethodsMyOtherInnerClass);
+
+  if (env->RegisterNatives(g_MyOtherInnerClass_clazz,
+                           kMethodsMyOtherInnerClass,
+                           kMethodsMyOtherInnerClassSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  static const JNINativeMethod kMethodsTestJni[] = {
+    { "nativeInit",
+"("
+")"
+"I", reinterpret_cast<void*>(Init) },
+  };
+  const int kMethodsTestJniSize = arraysize(kMethodsTestJni);
+
+  if (env->RegisterNatives(g_TestJni_clazz,
+                           kMethodsTestJni,
+                           kMethodsTestJniSize) < 0) {
+    LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+    return false;
+  }
+
+  return true;
+}
+
+#endif  // org_chromium_TestJni_JNI
+"""
+    self.assertTextEquals(golden_content, h.GetContent())
+
+  def testCalledByNatives(self):
+    test_data = """"
+    import android.graphics.Bitmap;
+    import android.view.View;
+    import java.io.InputStream;
+
+    class InnerClass {}
+
+    @CalledByNative
+    InnerClass showConfirmInfoBar(int nativeInfoBar,
+            String buttonOk, String buttonCancel, String title, Bitmap icon) {
+        InfoBar infobar = new ConfirmInfoBar(nativeInfoBar, mContext,
+                                             buttonOk, buttonCancel,
+                                             title, icon);
+        return infobar;
+    }
+    @CalledByNative
+    InnerClass showAutoLoginInfoBar(int nativeInfoBar,
+            String realm, String account, String args) {
+        AutoLoginInfoBar infobar = new AutoLoginInfoBar(nativeInfoBar, mContext,
+                realm, account, args);
+        if (infobar.displayedAccountCount() == 0)
+            infobar = null;
+        return infobar;
+    }
+    @CalledByNative("InfoBar")
+    void dismiss();
+    @SuppressWarnings("unused")
+    @CalledByNative
+    private static boolean shouldShowAutoLogin(View view,
+            String realm, String account, String args) {
+        AccountManagerContainer accountManagerContainer =
+            new AccountManagerContainer((Activity)contentView.getContext(),
+            realm, account, args);
+        String[] logins = accountManagerContainer.getAccountLogins(null);
+        return logins.length != 0;
+    }
+    @CalledByNative
+    static InputStream openUrl(String url) {
+        return null;
+    }
+    @CalledByNative
+    private void activateHardwareAcceleration(final boolean activated,
+            final int iPid, final int iType,
+            final int iPrimaryID, final int iSecondaryID) {
+      if (!activated) {
+          return
+      }
+    }
+    @CalledByNativeUnchecked
+    private void uncheckedCall(int iParam);
+    """
+    jni_generator.JniParams.SetFullyQualifiedClass('org/chromium/Foo')
+    jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
+    called_by_natives = jni_generator.ExtractCalledByNatives(test_data)
+    golden_called_by_natives = [
+        CalledByNative(
+            return_type='InnerClass',
+            system_class=False,
+            static=False,
+            name='showConfirmInfoBar',
+            method_id_var_name='showConfirmInfoBar',
+            java_class_name='',
+            params=[Param(datatype='int', name='nativeInfoBar'),
+                    Param(datatype='String', name='buttonOk'),
+                    Param(datatype='String', name='buttonCancel'),
+                    Param(datatype='String', name='title'),
+                    Param(datatype='Bitmap', name='icon')],
+            env_call=('Object', ''),
+            unchecked=False,
+        ),
+        CalledByNative(
+            return_type='InnerClass',
+            system_class=False,
+            static=False,
+            name='showAutoLoginInfoBar',
+            method_id_var_name='showAutoLoginInfoBar',
+            java_class_name='',
+            params=[Param(datatype='int', name='nativeInfoBar'),
+                    Param(datatype='String', name='realm'),
+                    Param(datatype='String', name='account'),
+                    Param(datatype='String', name='args')],
+            env_call=('Object', ''),
+            unchecked=False,
+        ),
+        CalledByNative(
+            return_type='void',
+            system_class=False,
+            static=False,
+            name='dismiss',
+            method_id_var_name='dismiss',
+            java_class_name='InfoBar',
+            params=[],
+            env_call=('Void', ''),
+            unchecked=False,
+        ),
+        CalledByNative(
+            return_type='boolean',
+            system_class=False,
+            static=True,
+            name='shouldShowAutoLogin',
+            method_id_var_name='shouldShowAutoLogin',
+            java_class_name='',
+            params=[Param(datatype='View', name='view'),
+                    Param(datatype='String', name='realm'),
+                    Param(datatype='String', name='account'),
+                    Param(datatype='String', name='args')],
+            env_call=('Boolean', ''),
+            unchecked=False,
+        ),
+        CalledByNative(
+            return_type='InputStream',
+            system_class=False,
+            static=True,
+            name='openUrl',
+            method_id_var_name='openUrl',
+            java_class_name='',
+            params=[Param(datatype='String', name='url')],
+            env_call=('Object', ''),
+            unchecked=False,
+        ),
+        CalledByNative(
+            return_type='void',
+            system_class=False,
+            static=False,
+            name='activateHardwareAcceleration',
+            method_id_var_name='activateHardwareAcceleration',
+            java_class_name='',
+            params=[Param(datatype='boolean', name='activated'),
+                    Param(datatype='int', name='iPid'),
+                    Param(datatype='int', name='iType'),
+                    Param(datatype='int', name='iPrimaryID'),
+                    Param(datatype='int', name='iSecondaryID'),
+                   ],
+            env_call=('Void', ''),
+            unchecked=False,
+        ),
+        CalledByNative(
+            return_type='void',
+            system_class=False,
+            static=False,
+            name='uncheckedCall',
+            method_id_var_name='uncheckedCall',
+            java_class_name='',
+            params=[Param(datatype='int', name='iParam')],
+            env_call=('Void', ''),
+            unchecked=True,
+        ),
+    ]
+    self.assertListEquals(golden_called_by_natives, called_by_natives)
+    h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
+                                             [], called_by_natives)
+    golden_content = """\
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     base/android/jni_generator/jni_generator_tests.py
+// For
+//     org/chromium/TestJni
+
+#ifndef org_chromium_TestJni_JNI
+#define org_chromium_TestJni_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kTestJniClassPath[] = "org/chromium/TestJni";
+const char kInfoBarClassPath[] = "org/chromium/TestJni$InfoBar";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_TestJni_clazz = NULL;
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_InfoBar_clazz = NULL;
+}  // namespace
+
+// Step 2: method stubs.
+
+static base::subtle::AtomicWord g_TestJni_showConfirmInfoBar = 0;
+static ScopedJavaLocalRef<jobject> Java_TestJni_showConfirmInfoBar(JNIEnv* env,
+    jobject obj, jint nativeInfoBar,
+    jstring buttonOk,
+    jstring buttonCancel,
+    jstring title,
+    jobject icon) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_TestJni_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_TestJni_clazz,
+      "showConfirmInfoBar",
+
+"("
+"I"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+"Landroid/graphics/Bitmap;"
+")"
+"Lorg/chromium/Foo$InnerClass;",
+      &g_TestJni_showConfirmInfoBar);
+
+  jobject ret =
+    env->CallObjectMethod(obj,
+      method_id, nativeInfoBar, buttonOk, buttonCancel, title, icon);
+  base::android::CheckException(env);
+  return ScopedJavaLocalRef<jobject>(env, ret);
+}
+
+static base::subtle::AtomicWord g_TestJni_showAutoLoginInfoBar = 0;
+static ScopedJavaLocalRef<jobject> Java_TestJni_showAutoLoginInfoBar(JNIEnv*
+    env, jobject obj, jint nativeInfoBar,
+    jstring realm,
+    jstring account,
+    jstring args) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_TestJni_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_TestJni_clazz,
+      "showAutoLoginInfoBar",
+
+"("
+"I"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+")"
+"Lorg/chromium/Foo$InnerClass;",
+      &g_TestJni_showAutoLoginInfoBar);
+
+  jobject ret =
+    env->CallObjectMethod(obj,
+      method_id, nativeInfoBar, realm, account, args);
+  base::android::CheckException(env);
+  return ScopedJavaLocalRef<jobject>(env, ret);
+}
+
+static base::subtle::AtomicWord g_InfoBar_dismiss = 0;
+static void Java_InfoBar_dismiss(JNIEnv* env, jobject obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InfoBar_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InfoBar_clazz,
+      "dismiss",
+
+"("
+")"
+"V",
+      &g_InfoBar_dismiss);
+
+  env->CallVoidMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+
+}
+
+static base::subtle::AtomicWord g_TestJni_shouldShowAutoLogin = 0;
+static jboolean Java_TestJni_shouldShowAutoLogin(JNIEnv* env, jobject view,
+    jstring realm,
+    jstring account,
+    jstring args) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_TestJni_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_STATIC>(
+      env, g_TestJni_clazz,
+      "shouldShowAutoLogin",
+
+"("
+"Landroid/view/View;"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+")"
+"Z",
+      &g_TestJni_shouldShowAutoLogin);
+
+  jboolean ret =
+    env->CallStaticBooleanMethod(g_TestJni_clazz,
+      method_id, view, realm, account, args);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_TestJni_openUrl = 0;
+static ScopedJavaLocalRef<jobject> Java_TestJni_openUrl(JNIEnv* env, jstring
+    url) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_TestJni_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_STATIC>(
+      env, g_TestJni_clazz,
+      "openUrl",
+
+"("
+"Ljava/lang/String;"
+")"
+"Ljava/io/InputStream;",
+      &g_TestJni_openUrl);
+
+  jobject ret =
+    env->CallStaticObjectMethod(g_TestJni_clazz,
+      method_id, url);
+  base::android::CheckException(env);
+  return ScopedJavaLocalRef<jobject>(env, ret);
+}
+
+static base::subtle::AtomicWord g_TestJni_activateHardwareAcceleration = 0;
+static void Java_TestJni_activateHardwareAcceleration(JNIEnv* env, jobject obj,
+    jboolean activated,
+    jint iPid,
+    jint iType,
+    jint iPrimaryID,
+    jint iSecondaryID) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_TestJni_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_TestJni_clazz,
+      "activateHardwareAcceleration",
+
+"("
+"Z"
+"I"
+"I"
+"I"
+"I"
+")"
+"V",
+      &g_TestJni_activateHardwareAcceleration);
+
+  env->CallVoidMethod(obj,
+      method_id, activated, iPid, iType, iPrimaryID, iSecondaryID);
+  base::android::CheckException(env);
+
+}
+
+static base::subtle::AtomicWord g_TestJni_uncheckedCall = 0;
+static void Java_TestJni_uncheckedCall(JNIEnv* env, jobject obj, jint iParam) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_TestJni_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_TestJni_clazz,
+      "uncheckedCall",
+
+"("
+"I"
+")"
+"V",
+      &g_TestJni_uncheckedCall);
+
+  env->CallVoidMethod(obj,
+      method_id, iParam);
+
+}
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kTestJniClassPath)));
+  g_InfoBar_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kInfoBarClassPath)));
+  return true;
+}
+
+#endif  // org_chromium_TestJni_JNI
+"""
+    self.assertTextEquals(golden_content, h.GetContent())
+
+  def testCalledByNativeParseError(self):
+    try:
+      jni_generator.ExtractCalledByNatives("""
+@CalledByNative
+public static int foo(); // This one is fine
+
+@CalledByNative
+scooby doo
+""")
+      self.fail('Expected a ParseError')
+    except jni_generator.ParseError, e:
+      self.assertEquals(('@CalledByNative', 'scooby doo'), e.context_lines)
+
+  def testFullyQualifiedClassName(self):
+    contents = """
+// 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.
+
+package org.chromium.content.browser;
+
+import org.chromium.base.BuildInfo;
+"""
+    self.assertEquals('org/chromium/content/browser/Foo',
+                      jni_generator.ExtractFullyQualifiedJavaClassName(
+                          'org/chromium/content/browser/Foo.java', contents))
+    self.assertEquals('org/chromium/content/browser/Foo',
+                      jni_generator.ExtractFullyQualifiedJavaClassName(
+                          'frameworks/Foo.java', contents))
+    self.assertRaises(SyntaxError,
+                      jni_generator.ExtractFullyQualifiedJavaClassName,
+                      'com/foo/Bar', 'no PACKAGE line')
+
+  def testMethodNameMangling(self):
+    self.assertEquals('closeV',
+        jni_generator.GetMangledMethodName('close', [], 'void'))
+    self.assertEquals('readI_AB_I_I',
+        jni_generator.GetMangledMethodName('read',
+            [Param(name='p1',
+                   datatype='byte[]'),
+             Param(name='p2',
+                   datatype='int'),
+             Param(name='p3',
+                   datatype='int'),],
+             'int'))
+    self.assertEquals('openJIIS_JLS',
+        jni_generator.GetMangledMethodName('open',
+            [Param(name='p1',
+                   datatype='java/lang/String'),],
+             'java/io/InputStream'))
+
+  def testFromJavaP(self):
+    contents = """
+public abstract class java.io.InputStream extends java.lang.Object
+      implements java.io.Closeable{
+    public java.io.InputStream();
+    public int available()       throws java.io.IOException;
+    public void close()       throws java.io.IOException;
+    public void mark(int);
+    public boolean markSupported();
+    public abstract int read()       throws java.io.IOException;
+    public int read(byte[])       throws java.io.IOException;
+    public int read(byte[], int, int)       throws java.io.IOException;
+    public synchronized void reset()       throws java.io.IOException;
+    public long skip(long)       throws java.io.IOException;
+}
+"""
+    jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), None)
+    self.assertEquals(10, len(jni_from_javap.called_by_natives))
+    golden_content = """\
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     base/android/jni_generator/jni_generator_tests.py
+// For
+//     java/io/InputStream
+
+#ifndef java_io_InputStream_JNI
+#define java_io_InputStream_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kInputStreamClassPath[] = "java/io/InputStream";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_InputStream_clazz = NULL;
+}  // namespace
+
+namespace JNI_InputStream {
+
+// Step 2: method stubs.
+
+static base::subtle::AtomicWord g_InputStream_available = 0;
+static jint Java_InputStream_available(JNIEnv* env, jobject obj) __attribute__
+    ((unused));
+static jint Java_InputStream_available(JNIEnv* env, jobject obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "available",
+
+"("
+")"
+"I",
+      &g_InputStream_available);
+
+  jint ret =
+    env->CallIntMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_InputStream_close = 0;
+static void Java_InputStream_close(JNIEnv* env, jobject obj) __attribute__
+    ((unused));
+static void Java_InputStream_close(JNIEnv* env, jobject obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "close",
+
+"("
+")"
+"V",
+      &g_InputStream_close);
+
+  env->CallVoidMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+
+}
+
+static base::subtle::AtomicWord g_InputStream_mark = 0;
+static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0)
+    __attribute__ ((unused));
+static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "mark",
+
+"("
+"I"
+")"
+"V",
+      &g_InputStream_mark);
+
+  env->CallVoidMethod(obj,
+      method_id, p0);
+  base::android::CheckException(env);
+
+}
+
+static base::subtle::AtomicWord g_InputStream_markSupported = 0;
+static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj)
+    __attribute__ ((unused));
+static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "markSupported",
+
+"("
+")"
+"Z",
+      &g_InputStream_markSupported);
+
+  jboolean ret =
+    env->CallBooleanMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_InputStream_readI = 0;
+static jint Java_InputStream_readI(JNIEnv* env, jobject obj) __attribute__
+    ((unused));
+static jint Java_InputStream_readI(JNIEnv* env, jobject obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "read",
+
+"("
+")"
+"I",
+      &g_InputStream_readI);
+
+  jint ret =
+    env->CallIntMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_InputStream_readI_AB = 0;
+static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0)
+    __attribute__ ((unused));
+static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "read",
+
+"("
+"[B"
+")"
+"I",
+      &g_InputStream_readI_AB);
+
+  jint ret =
+    env->CallIntMethod(obj,
+      method_id, p0);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_InputStream_readI_AB_I_I = 0;
+static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray
+    p0,
+    jint p1,
+    jint p2) __attribute__ ((unused));
+static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray
+    p0,
+    jint p1,
+    jint p2) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "read",
+
+"("
+"[B"
+"I"
+"I"
+")"
+"I",
+      &g_InputStream_readI_AB_I_I);
+
+  jint ret =
+    env->CallIntMethod(obj,
+      method_id, p0, p1, p2);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_InputStream_reset = 0;
+static void Java_InputStream_reset(JNIEnv* env, jobject obj) __attribute__
+    ((unused));
+static void Java_InputStream_reset(JNIEnv* env, jobject obj) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "reset",
+
+"("
+")"
+"V",
+      &g_InputStream_reset);
+
+  env->CallVoidMethod(obj,
+      method_id);
+  base::android::CheckException(env);
+
+}
+
+static base::subtle::AtomicWord g_InputStream_skip = 0;
+static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0)
+    __attribute__ ((unused));
+static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "skip",
+
+"("
+"J"
+")"
+"J",
+      &g_InputStream_skip);
+
+  jlong ret =
+    env->CallLongMethod(obj,
+      method_id, p0);
+  base::android::CheckException(env);
+  return ret;
+}
+
+static base::subtle::AtomicWord g_InputStream_Constructor = 0;
+static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env)
+    __attribute__ ((unused));
+static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env) {
+  /* Must call RegisterNativesImpl()  */
+  DCHECK(g_InputStream_clazz);
+  jmethodID method_id =
+  base::android::MethodID::LazyGet<
+      base::android::MethodID::TYPE_INSTANCE>(
+      env, g_InputStream_clazz,
+      "<init>",
+
+"("
+")"
+"V",
+      &g_InputStream_Constructor);
+
+  jobject ret =
+    env->NewObject(g_InputStream_clazz,
+      method_id);
+  base::android::CheckException(env);
+  return ScopedJavaLocalRef<jobject>(env, ret);
+}
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_InputStream_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetUnscopedClass(env, kInputStreamClassPath)));
+  return true;
+}
+}  // namespace JNI_InputStream
+
+#endif  // java_io_InputStream_JNI
+"""
+    self.assertTextEquals(golden_content, jni_from_javap.GetContent())
+
+  def testREForNatives(self):
+    # We should not match "native SyncSetupFlow" inside the comment.
+    test_data = """
+    /**
+     * Invoked when the setup process is complete so we can disconnect from the
+     * native-side SyncSetupFlowHandler.
+     */
+    public void destroy() {
+        Log.v(TAG, "Destroying native SyncSetupFlow");
+        if (mNativeSyncSetupFlow != 0) {
+            nativeSyncSetupEnded(mNativeSyncSetupFlow);
+            mNativeSyncSetupFlow = 0;
+        }
+    }
+    private native void nativeSyncSetupEnded(
+        int nativeAndroidSyncSetupFlowHandler);
+    """
+    jni_from_java = jni_generator.JNIFromJavaSource(test_data, 'foo/bar')
+
+  def testRaisesOnNonJNIMethod(self):
+    test_data = """
+    class MyInnerClass {
+      private int Foo(int p0) {
+      }
+    }
+    """
+    self.assertRaises(SyntaxError,
+                      jni_generator.JNIFromJavaSource,
+                      test_data, 'foo/bar')
+
+  def testJniSelfDocumentingExample(self):
+    script_dir = os.path.dirname(sys.argv[0])
+    content = file(os.path.join(script_dir, 'SampleForTests.java')).read()
+    golden_content = file(os.path.join(script_dir,
+                                       'golden_sample_for_tests_jni.h')).read()
+    jni_from_java = jni_generator.JNIFromJavaSource(
+        content, 'org/chromium/example/jni_generator/SampleForTests')
+    self.assertTextEquals(golden_content, jni_from_java.GetContent())
+
+  def testNoWrappingPreprocessorLines(self):
+    test_data = """
+    package com.google.lookhowextremelylongiam.snarf.icankeepthisupallday;
+
+    class ReallyLongClassNamesAreAllTheRage {
+        private static native int nativeTest();
+    }
+    """
+    jni_from_java = jni_generator.JNIFromJavaSource(
+        test_data, ('com/google/lookhowextremelylongiam/snarf/'
+                    'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'))
+    jni_lines = jni_from_java.GetContent().split('\n')
+    line = filter(lambda line: line.lstrip().startswith('#ifndef'),
+                  jni_lines)[0]
+    self.assertTrue(len(line) > 80,
+                    ('Expected #ifndef line to be > 80 chars: ', line))
+
+  def testImports(self):
+    import_header = """
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.app;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.ArrayList;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.content.app.ContentMain;
+import org.chromium.content.browser.SandboxedProcessConnection;
+import org.chromium.content.common.ISandboxedProcessCallback;
+import org.chromium.content.common.ISandboxedProcessService;
+import org.chromium.content.common.SurfaceCallback;
+import org.chromium.content.common.WillNotRaise.AnException;
+import org.chromium.content.common.WillRaise.AnException;
+
+import static org.chromium.Bar.Zoo;
+
+class Foo {
+  public static class BookmarkNode implements Parcelable {
+  }
+  public interface PasswordListObserver {
+  }
+}
+    """
+    jni_generator.JniParams.SetFullyQualifiedClass(
+        'org/chromium/content/app/Foo')
+    jni_generator.JniParams.ExtractImportsAndInnerClasses(import_header)
+    self.assertTrue('Lorg/chromium/content/common/ISandboxedProcessService' in
+                    jni_generator.JniParams._imports)
+    self.assertTrue('Lorg/chromium/Bar/Zoo' in
+                    jni_generator.JniParams._imports)
+    self.assertTrue('Lorg/chromium/content/app/Foo$BookmarkNode' in
+                    jni_generator.JniParams._inner_classes)
+    self.assertTrue('Lorg/chromium/content/app/Foo$PasswordListObserver' in
+                    jni_generator.JniParams._inner_classes)
+    self.assertEquals('Lorg/chromium/content/app/ContentMain$Inner',
+                      jni_generator.JniParams.JavaToJni('ContentMain.Inner'))
+    self.assertRaises(SyntaxError,
+                      jni_generator.JniParams.JavaToJni,
+                      'AnException')
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/base/android/jni_generator/sample_for_tests.cc b/src/base/android/jni_generator/sample_for_tests.cc
new file mode 100644
index 0000000..5b5cfc5
--- /dev/null
+++ b/src/base/android/jni_generator/sample_for_tests.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+
+// The main purpose of this is to ensure sample_for_tests_jni.h
+// compiles and the functions declared in it as expected.
+
+using base::android::AttachCurrentThread;
+using base::android::ScopedJavaLocalRef;
+
+namespace base {
+namespace android {
+
+class CPPClass {
+ public:
+  class InnerClass {
+   public:
+    jdouble MethodOtherP0(JNIEnv* env, jobject obj) {
+      return 0.0;
+    }
+  };
+
+  void Destroy(JNIEnv* env, jobject obj) {
+    delete this;
+  }
+
+  jint Method(JNIEnv* env, jobject obj) {
+    return 0;
+  }
+
+  ScopedJavaLocalRef<jstring> InnerMethod(JNIEnv* env, jobject obj) {
+    return ScopedJavaLocalRef<jstring>();
+  }
+};
+
+static jint Init(JNIEnv* env, jobject obj) {
+  return 0;
+}
+
+static jdouble GetDoubleFunction(JNIEnv*, jobject) {
+  return 0;
+}
+
+static jfloat GetFloatFunction(JNIEnv*, jclass) {
+  return 0;
+}
+
+static void SetNonPODDatatype(JNIEnv*, jobject, jobject) {}
+
+static jobject GetNonPODDatatype(JNIEnv*, jobject) {
+  return NULL;
+}
+
+static jint InnerFunction(JNIEnv*, jclass) {
+  return 0;
+}
+
+} // namespace android
+} // namespace base
+
+#include "jni/SampleForTests_jni.h"
+
+int main() {
+  // On a regular application, you'd call AttachCurrentThread(). This sample is
+  // not yet linking with all the libraries.
+  JNIEnv* env = /* AttachCurrentThread() */ NULL;
+
+  // This is how you call a java static method from C++.
+  bool foo = base::android::Java_SampleForTests_staticJavaMethod(env);
+
+  // This is how you call a java method from C++. Note that you must have
+  // obtained the jobject somehow.
+  jobject my_java_object = NULL;
+  int bar = base::android::Java_SampleForTests_javaMethod(
+      env, my_java_object, 1, 2);
+
+  return 0;
+}
diff --git a/src/base/android/jni_helper.cc b/src/base/android/jni_helper.cc
new file mode 100644
index 0000000..c0833c9
--- /dev/null
+++ b/src/base/android/jni_helper.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_helper.h"
+
+#include "base/android/jni_android.h"
+#include "base/logging.h"
+
+using base::android::AttachCurrentThread;
+
+JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef()
+  : obj_(NULL) {
+}
+
+JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef(
+    const JavaObjectWeakGlobalRef& orig) {
+  Assign(orig);
+}
+
+JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef(JNIEnv* env, jobject obj)
+    : obj_(env->NewWeakGlobalRef(obj)) {
+  DCHECK(obj_);
+}
+
+JavaObjectWeakGlobalRef::~JavaObjectWeakGlobalRef() {
+  reset();
+}
+
+void JavaObjectWeakGlobalRef::operator=(const JavaObjectWeakGlobalRef& rhs) {
+  Assign(rhs);
+}
+
+void JavaObjectWeakGlobalRef::reset() {
+  if (obj_) {
+    AttachCurrentThread()->DeleteWeakGlobalRef(obj_);
+    obj_ = NULL;
+  }
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+    JavaObjectWeakGlobalRef::get(JNIEnv* env) const {
+  return GetRealObject(env, obj_);
+}
+
+base::android::ScopedJavaLocalRef<jobject> GetRealObject(
+    JNIEnv* env, jweak obj) {
+  jobject real = NULL;
+  if (obj) {
+    real = env->NewLocalRef(obj);
+    if (!real)
+      DLOG(ERROR) << "The real object has been deleted!";
+  }
+  return base::android::ScopedJavaLocalRef<jobject>(env, real);
+}
+
+void JavaObjectWeakGlobalRef::Assign(const JavaObjectWeakGlobalRef& other) {
+  JNIEnv* env = AttachCurrentThread();
+  obj_ = env->NewWeakGlobalRef(other.obj_);
+}
diff --git a/src/base/android/jni_helper.h b/src/base/android/jni_helper.h
new file mode 100644
index 0000000..895bf95
--- /dev/null
+++ b/src/base/android/jni_helper.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_JNI_HELPER_H_
+#define BASE_ANDROID_JNI_HELPER_H_
+
+#include <jni.h>
+
+#include "base/base_export.h"
+#include "base/android/scoped_java_ref.h"
+
+// Manages WeakGlobalRef lifecycle.
+// This class is not thread-safe w.r.t. get() and reset(). Multiple threads may
+// safely use get() concurrently, but if the user calls reset() (or of course,
+// calls the destructor) they'll need to provide their own synchronization.
+class BASE_EXPORT JavaObjectWeakGlobalRef {
+ public:
+  JavaObjectWeakGlobalRef();
+  JavaObjectWeakGlobalRef(const JavaObjectWeakGlobalRef& orig);
+  JavaObjectWeakGlobalRef(JNIEnv* env, jobject obj);
+  virtual ~JavaObjectWeakGlobalRef();
+
+  void operator=(const JavaObjectWeakGlobalRef& rhs);
+
+  base::android::ScopedJavaLocalRef<jobject> get(JNIEnv* env) const;
+
+  void reset();
+
+ private:
+  void Assign(const JavaObjectWeakGlobalRef& rhs);
+
+  jweak obj_;
+};
+
+// Get the real object stored in the weak reference returned as a
+// ScopedJavaLocalRef.
+BASE_EXPORT base::android::ScopedJavaLocalRef<jobject> GetRealObject(
+    JNIEnv* env, jweak obj);
+
+#endif  // BASE_ANDROID_JNI_HELPER_H_
diff --git a/src/base/android/jni_registrar.cc b/src/base/android/jni_registrar.cc
new file mode 100644
index 0000000..696924a
--- /dev/null
+++ b/src/base/android/jni_registrar.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_registrar.h"
+
+#include "base/logging.h"
+#include "base/android/jni_android.h"
+
+namespace base {
+namespace android {
+
+bool RegisterNativeMethods(JNIEnv* env,
+                           const RegistrationMethod* method,
+                           size_t count) {
+  const RegistrationMethod* end = method + count;
+  while (method != end) {
+    if (!method->func(env) < 0) {
+      DLOG(ERROR) << method->name << " failed registration!";
+      return false;
+    }
+    method++;
+  }
+  return true;
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/jni_registrar.h b/src/base/android/jni_registrar.h
new file mode 100644
index 0000000..849d07f
--- /dev/null
+++ b/src/base/android/jni_registrar.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_JNI_REGISTRAR_H_
+#define BASE_ANDROID_JNI_REGISTRAR_H_
+
+#include <jni.h>
+#include "base/base_export.h"
+#include "base/basictypes.h"
+
+namespace base {
+namespace android {
+
+struct RegistrationMethod;
+
+// Registers the JNI bindings for the specified |method| definition containing
+// |count| elements.  Returns whether the registration of the given methods
+// succeeded.
+BASE_EXPORT bool RegisterNativeMethods(JNIEnv* env,
+                                       const RegistrationMethod* method,
+                                       size_t count);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_JNI_REGISTRAR_H_
diff --git a/src/base/android/jni_string.cc b/src/base/android/jni_string.cc
new file mode 100644
index 0000000..ac3975f
--- /dev/null
+++ b/src/base/android/jni_string.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_string.h"
+
+#include "base/android/jni_android.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+
+namespace {
+
+// Internal version that does not use a scoped local pointer.
+jstring ConvertUTF16ToJavaStringImpl(JNIEnv* env,
+                                     const base::StringPiece16& str) {
+  jstring result = env->NewString(str.data(), str.length());
+  base::android::CheckException(env);
+  return result;
+}
+
+}
+
+namespace base {
+namespace android {
+
+void ConvertJavaStringToUTF8(JNIEnv* env, jstring str, std::string* result) {
+  if (!str) {
+    LOG(WARNING) << "ConvertJavaStringToUTF8 called with null string.";
+    result->clear();
+    return;
+  }
+  // JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so
+  // instead get the String in UTF16 and convert using chromium's conversion
+  // function that yields plain (non Java-modified) UTF8.
+  const jchar* chars = env->GetStringChars(str, NULL);
+  DCHECK(chars);
+  UTF16ToUTF8(chars, env->GetStringLength(str), result);
+  env->ReleaseStringChars(str, chars);
+  CheckException(env);
+}
+
+std::string ConvertJavaStringToUTF8(JNIEnv* env, jstring str) {
+  std::string result;
+  ConvertJavaStringToUTF8(env, str, &result);
+  return result;
+}
+
+std::string ConvertJavaStringToUTF8(const JavaRef<jstring>& str) {
+  return ConvertJavaStringToUTF8(AttachCurrentThread(), str.obj());
+}
+
+ScopedJavaLocalRef<jstring> ConvertUTF8ToJavaString(
+    JNIEnv* env,
+    const base::StringPiece& str) {
+  // JNI's NewStringUTF expects "modified" UTF8 so instead create the string
+  // via our own UTF16 conversion utility.
+  // Further, Dalvik requires the string passed into NewStringUTF() to come from
+  // a trusted source. We can't guarantee that all UTF8 will be sanitized before
+  // it gets here, so constructing via UTF16 side-steps this issue.
+  // (Dalvik stores strings internally as UTF16 anyway, so there shouldn't be
+  // a significant performance hit by doing it this way).
+  return ScopedJavaLocalRef<jstring>(env, ConvertUTF16ToJavaStringImpl(
+      env, UTF8ToUTF16(str)));
+}
+
+void ConvertJavaStringToUTF16(JNIEnv* env, jstring str, string16* result) {
+  if (!str) {
+    LOG(WARNING) << "ConvertJavaStringToUTF16 called with null string.";
+    result->clear();
+    return;
+  }
+  const jchar* chars = env->GetStringChars(str, NULL);
+  DCHECK(chars);
+  // GetStringChars isn't required to NULL-terminate the strings
+  // it returns, so the length must be explicitly checked.
+  result->assign(chars, env->GetStringLength(str));
+  env->ReleaseStringChars(str, chars);
+  CheckException(env);
+}
+
+string16 ConvertJavaStringToUTF16(JNIEnv* env, jstring str) {
+  string16 result;
+  ConvertJavaStringToUTF16(env, str, &result);
+  return result;
+}
+
+string16 ConvertJavaStringToUTF16(const JavaRef<jstring>& str) {
+  return ConvertJavaStringToUTF16(AttachCurrentThread(), str.obj());
+}
+
+ScopedJavaLocalRef<jstring> ConvertUTF16ToJavaString(
+    JNIEnv* env,
+    const base::StringPiece16& str) {
+  return ScopedJavaLocalRef<jstring>(env,
+                                     ConvertUTF16ToJavaStringImpl(env, str));
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/jni_string.h b/src/base/android/jni_string.h
new file mode 100644
index 0000000..222b78d
--- /dev/null
+++ b/src/base/android/jni_string.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_JNI_STRING_H_
+#define BASE_ANDROID_JNI_STRING_H_
+
+#include <jni.h>
+#include <string>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/base_export.h"
+#include "base/string_piece.h"
+
+namespace base {
+namespace android {
+
+// Convert a Java string to UTF8. Returns a std string.
+BASE_EXPORT void ConvertJavaStringToUTF8(JNIEnv* env,
+                                         jstring str,
+                                         std::string* result);
+BASE_EXPORT std::string ConvertJavaStringToUTF8(JNIEnv* env, jstring str);
+BASE_EXPORT std::string ConvertJavaStringToUTF8(const JavaRef<jstring>& str);
+
+// Convert a std string to Java string.
+BASE_EXPORT ScopedJavaLocalRef<jstring> ConvertUTF8ToJavaString(
+    JNIEnv* env,
+    const base::StringPiece& str);
+
+// Convert a Java string to UTF16. Returns a string16.
+BASE_EXPORT void ConvertJavaStringToUTF16(JNIEnv* env,
+                                          jstring str,
+                                          string16* result);
+BASE_EXPORT string16 ConvertJavaStringToUTF16(JNIEnv* env, jstring str);
+BASE_EXPORT string16 ConvertJavaStringToUTF16(const JavaRef<jstring>& str);
+
+// Convert a string16 to a Java string.
+BASE_EXPORT ScopedJavaLocalRef<jstring> ConvertUTF16ToJavaString(
+    JNIEnv* env,
+    const base::StringPiece16& str);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_JNI_STRING_H_
diff --git a/src/base/android/jni_string_unittest.cc b/src/base/android/jni_string_unittest.cc
new file mode 100644
index 0000000..59a847e
--- /dev/null
+++ b/src/base/android/jni_string_unittest.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_string.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace android {
+
+TEST(JniString, BasicConversionsUTF8) {
+  const std::string kSimpleString = "SimpleTest8";
+  JNIEnv* env = AttachCurrentThread();
+  std::string result =
+      ConvertJavaStringToUTF8(ConvertUTF8ToJavaString(env, kSimpleString));
+  EXPECT_EQ(kSimpleString, result);
+}
+
+TEST(JniString, BasicConversionsUTF16) {
+  const string16 kSimpleString = UTF8ToUTF16("SimpleTest16");
+  JNIEnv* env = AttachCurrentThread();
+  string16 result =
+      ConvertJavaStringToUTF16(ConvertUTF16ToJavaString(env, kSimpleString));
+  EXPECT_EQ(kSimpleString, result);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/locale_utils.cc b/src/base/android/locale_utils.cc
new file mode 100644
index 0000000..60b8f84
--- /dev/null
+++ b/src/base/android/locale_utils.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/locale_utils.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "jni/LocaleUtils_jni.h"
+#include "unicode/uloc.h"
+
+namespace base {
+namespace android {
+
+std::string GetDefaultLocale() {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> locale = Java_LocaleUtils_getDefaultLocale(env);
+  return ConvertJavaStringToUTF8(locale);
+}
+
+namespace {
+
+// Common prototype of ICU uloc_getXXX() functions.
+typedef int32_t (*UlocGetComponentFunc)(const char*, char*, int32_t,
+                                        UErrorCode*);
+
+std::string GetLocaleComponent(const std::string& locale,
+                               UlocGetComponentFunc uloc_func,
+                               int32_t max_capacity) {
+  std::string result;
+  UErrorCode error = U_ZERO_ERROR;
+  int32_t actual_length = uloc_func(locale.c_str(),
+                                    WriteInto(&result, max_capacity),
+                                    max_capacity,
+                                    &error);
+  DCHECK(U_SUCCESS(error));
+  DCHECK(actual_length < max_capacity);
+  result.resize(actual_length);
+  return result;
+}
+
+ScopedJavaLocalRef<jobject> NewJavaLocale(
+    JNIEnv* env,
+    ScopedJavaLocalRef<jclass> locale_class,
+    jmethodID constructor_id,
+    const std::string& locale) {
+  // TODO(wangxianzhu): Use new Locale API once Android supports scripts.
+  std::string language = GetLocaleComponent(
+      locale, uloc_getLanguage, ULOC_LANG_CAPACITY);
+  std::string country = GetLocaleComponent(
+      locale, uloc_getCountry, ULOC_COUNTRY_CAPACITY);
+  std::string variant = GetLocaleComponent(
+      locale, uloc_getVariant, ULOC_FULLNAME_CAPACITY);
+  return ScopedJavaLocalRef<jobject>(
+      env, env->NewObject(
+          locale_class.obj(), constructor_id,
+          ConvertUTF8ToJavaString(env, language).obj(),
+          ConvertUTF8ToJavaString(env, country).obj(),
+          ConvertUTF8ToJavaString(env, variant).obj()));
+}
+
+}  // namespace
+
+string16 GetDisplayNameForLocale(const std::string& locale,
+                                 const std::string& display_locale) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jclass> locale_class = GetClass(env, "java/util/Locale");
+  jmethodID constructor_id = MethodID::Get<MethodID::TYPE_INSTANCE>(
+      env, locale_class.obj(), "<init>",
+      "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+  ScopedJavaLocalRef<jobject> java_locale = NewJavaLocale(
+      env, locale_class, constructor_id, locale);
+  ScopedJavaLocalRef<jobject> java_display_locale = NewJavaLocale(
+      env, locale_class, constructor_id, display_locale);
+
+  jmethodID method_id = MethodID::Get<MethodID::TYPE_INSTANCE>(
+      env, locale_class.obj(), "getDisplayName",
+      "(Ljava/util/Locale;)Ljava/lang/String;");
+  ScopedJavaLocalRef<jstring> java_result(
+      env,
+      static_cast<jstring>(env->CallObjectMethod(java_locale.obj(), method_id,
+                                                 java_display_locale.obj())));
+  return ConvertJavaStringToUTF16(java_result);
+}
+
+bool RegisterLocaleUtils(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/locale_utils.h b/src/base/android/locale_utils.h
new file mode 100644
index 0000000..cef39f4
--- /dev/null
+++ b/src/base/android/locale_utils.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_LOCALE_UTILS_H_
+#define BASE_ANDROID_LOCALE_UTILS_H_
+
+#include <jni.h>
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/string16.h"
+
+namespace base {
+namespace android {
+
+// Return the current default locale of the device.
+BASE_EXPORT std::string GetDefaultLocale();
+
+BASE_EXPORT string16 GetDisplayNameForLocale(const std::string& locale,
+                                 const std::string& display_locale);
+
+bool RegisterLocaleUtils(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_LOCALE_UTILS_H_
diff --git a/src/base/android/path_service_android.cc b/src/base/android/path_service_android.cc
new file mode 100644
index 0000000..a9bf92d
--- /dev/null
+++ b/src/base/android/path_service_android.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/path_service_android.h"
+
+#include "base/file_path.h"
+#include "base/path_service.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "jni/PathService_jni.h"
+
+namespace base {
+namespace android {
+
+void Override(JNIEnv* env, jclass clazz, jint what, jstring path) {
+  FilePath file_path(ConvertJavaStringToUTF8(env, path));
+  PathService::Override(what, file_path);
+}
+
+bool RegisterPathService(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/path_service_android.h b/src/base/android/path_service_android.h
new file mode 100644
index 0000000..26040f9
--- /dev/null
+++ b/src/base/android/path_service_android.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_PATH_SERVICE_ANDROID_H_
+#define BASE_ANDROID_PATH_SERVICE_ANDROID_H_
+
+#include <jni.h>
+
+namespace base {
+namespace android {
+
+bool RegisterPathService(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_PATH_SERVICE_ANDROID_H_
diff --git a/src/base/android/path_utils.cc b/src/base/android/path_utils.cc
new file mode 100644
index 0000000..3d86177
--- /dev/null
+++ b/src/base/android/path_utils.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/path_utils.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/file_path.h"
+
+#include "jni/PathUtils_jni.h"
+
+namespace base {
+namespace android {
+
+bool GetDataDirectory(FilePath* result) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> path =
+      Java_PathUtils_getDataDirectory(env, GetApplicationContext());
+  FilePath data_path(ConvertJavaStringToUTF8(path));
+  *result = data_path;
+  return true;
+}
+
+bool GetCacheDirectory(FilePath* result) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> path =
+      Java_PathUtils_getCacheDirectory(env, GetApplicationContext());
+  FilePath cache_path(ConvertJavaStringToUTF8(path));
+  *result = cache_path;
+  return true;
+}
+
+bool GetDownloadsDirectory(FilePath* result) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> path =
+      Java_PathUtils_getDownloadsDirectory(env, GetApplicationContext());
+  FilePath downloads_path(ConvertJavaStringToUTF8(path));
+  *result = downloads_path;
+  return true;
+}
+
+bool GetNativeLibraryDirectory(FilePath* result) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> path =
+      Java_PathUtils_getNativeLibraryDirectory(env, GetApplicationContext());
+  FilePath library_path(ConvertJavaStringToUTF8(path));
+  *result = library_path;
+  return true;
+}
+
+bool GetExternalStorageDirectory(FilePath* result) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> path =
+      Java_PathUtils_getExternalStorageDirectory(env);
+  FilePath storage_path(ConvertJavaStringToUTF8(path));
+  *result = storage_path;
+  return true;
+}
+
+bool RegisterPathUtils(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/path_utils.h b/src/base/android/path_utils.h
new file mode 100644
index 0000000..78f0267
--- /dev/null
+++ b/src/base/android/path_utils.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_PATH_UTILS_H_
+#define BASE_ANDROID_PATH_UTILS_H_
+
+#include <jni.h>
+
+#include "base/base_export.h"
+
+class FilePath;
+
+namespace base {
+namespace android {
+
+// Retrieves the absolute path to the data directory of the current
+// application. The result is placed in the FilePath pointed to by 'result'.
+// This method is dedicated for base_paths_android.c, Using
+// PathService::Get(base::DIR_ANDROID_APP_DATA, ...) gets the data dir.
+BASE_EXPORT bool GetDataDirectory(FilePath* result);
+
+// Retrieves the absolute path to the cache directory. The result is placed in
+// the FilePath pointed to by 'result'. This method is dedicated for
+// base_paths_android.c, Using PathService::Get(base::DIR_CACHE, ...) gets the
+// cache dir.
+BASE_EXPORT bool GetCacheDirectory(FilePath* result);
+
+// Retrieves the path to the public downloads directory. The result is placed
+// in the FilePath pointed to by 'result'.
+bool GetDownloadsDirectory(FilePath* result);
+
+// Retrieves the path to the native JNI libraries via
+// ApplicationInfo.nativeLibraryDir on the Java side. The result is placed in
+// the FilePath pointed to by 'result'.
+BASE_EXPORT bool GetNativeLibraryDirectory(FilePath* result);
+
+// Retrieves the absolute path to the external storage directory. The result
+// is placed in the FilePath pointed to by 'result'.
+BASE_EXPORT bool GetExternalStorageDirectory(FilePath* result);
+
+bool RegisterPathUtils(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_PATH_UTILS_H_
diff --git a/src/base/android/path_utils_unittest.cc b/src/base/android/path_utils_unittest.cc
new file mode 100644
index 0000000..636e3fa
--- /dev/null
+++ b/src/base/android/path_utils_unittest.cc
@@ -0,0 +1,46 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/path_utils.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace android {
+
+typedef testing::Test PathUtilsTest;
+
+TEST_F(PathUtilsTest, TestGetDataDirectory) {
+  // The string comes from the Java side and depends on the APK
+  // we are running in. Assumes that we are packaged in
+  // org.chromium.native_test
+  FilePath path;
+  GetDataDirectory(&path);
+  EXPECT_STREQ("/data/data/org.chromium.native_test/app_chrome",
+               path.value().c_str());
+}
+
+TEST_F(PathUtilsTest, TestGetCacheDirectory) {
+  // The string comes from the Java side and depends on the APK
+  // we are running in. Assumes that we are packaged in
+  // org.chromium.native_test
+  FilePath path;
+  GetCacheDirectory(&path);
+  EXPECT_STREQ("/data/data/org.chromium.native_test/cache",
+               path.value().c_str());
+}
+
+TEST_F(PathUtilsTest, TestGetNativeLibraryDirectory) {
+  // The string comes from the Java side and depends on the APK
+  // we are running in. Assumes that the directory contains
+  // the base tests shared object.
+  FilePath path;
+  GetNativeLibraryDirectory(&path);
+  EXPECT_TRUE(file_util::PathExists(path.Append(("libbase_unittests.so"))));
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/scoped_java_ref.cc b/src/base/android/scoped_java_ref.cc
new file mode 100644
index 0000000..21b466e
--- /dev/null
+++ b/src/base/android/scoped_java_ref.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/scoped_java_ref.h"
+
+#include "base/android/jni_android.h"
+#include "base/logging.h"
+
+namespace base {
+namespace android {
+
+JavaRef<jobject>::JavaRef() : obj_(NULL) {}
+
+JavaRef<jobject>::JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {
+  if (obj) {
+    DCHECK(env && env->GetObjectRefType(obj) == JNILocalRefType);
+  }
+}
+
+JavaRef<jobject>::~JavaRef() {
+}
+
+JNIEnv* JavaRef<jobject>::SetNewLocalRef(JNIEnv* env, jobject obj) {
+  if (!env) {
+    env = AttachCurrentThread();
+  } else {
+    DCHECK_EQ(env, AttachCurrentThread());  // Is |env| on correct thread.
+  }
+  if (obj)
+    obj = env->NewLocalRef(obj);
+  if (obj_)
+    env->DeleteLocalRef(obj_);
+  obj_ = obj;
+  return env;
+}
+
+void JavaRef<jobject>::SetNewGlobalRef(JNIEnv* env, jobject obj) {
+  if (!env) {
+    env = AttachCurrentThread();
+  } else {
+    DCHECK_EQ(env, AttachCurrentThread());  // Is |env| on correct thread.
+  }
+  if (obj)
+    obj = env->NewGlobalRef(obj);
+  if (obj_)
+    env->DeleteGlobalRef(obj_);
+  obj_ = obj;
+}
+
+void JavaRef<jobject>::ResetLocalRef(JNIEnv* env) {
+  if (obj_) {
+    DCHECK_EQ(env, AttachCurrentThread());  // Is |env| on correct thread.
+    env->DeleteLocalRef(obj_);
+    obj_ = NULL;
+  }
+}
+
+void JavaRef<jobject>::ResetGlobalRef() {
+  if (obj_) {
+    AttachCurrentThread()->DeleteGlobalRef(obj_);
+    obj_ = NULL;
+  }
+}
+
+jobject JavaRef<jobject>::ReleaseInternal() {
+  jobject obj = obj_;
+  obj_ = NULL;
+  return obj;
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/android/scoped_java_ref.h b/src/base/android/scoped_java_ref.h
new file mode 100644
index 0000000..a5d71e2
--- /dev/null
+++ b/src/base/android/scoped_java_ref.h
@@ -0,0 +1,198 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_SCOPED_JAVA_REF_H_
+#define BASE_ANDROID_SCOPED_JAVA_REF_H_
+
+#include <jni.h>
+#include <stddef.h>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+
+namespace base {
+namespace android {
+
+// Forward declare the generic java reference template class.
+template<typename T> class JavaRef;
+
+// Template specialization of JavaRef, which acts as the base class for all
+// other JavaRef<> template types. This allows you to e.g. pass
+// ScopedJavaLocalRef<jstring> into a function taking const JavaRef<jobject>&
+template<>
+class BASE_EXPORT JavaRef<jobject> {
+ public:
+  jobject obj() const { return obj_; }
+
+  bool is_null() const { return obj_ == NULL; }
+
+ protected:
+  // Initializes a NULL reference.
+  JavaRef();
+
+  // Takes ownership of the |obj| reference passed; requires it to be a local
+  // reference type.
+  JavaRef(JNIEnv* env, jobject obj);
+
+  ~JavaRef();
+
+  // The following are implementation detail convenience methods, for
+  // use by the sub-classes.
+  JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj);
+  void SetNewGlobalRef(JNIEnv* env, jobject obj);
+  void ResetLocalRef(JNIEnv* env);
+  void ResetGlobalRef();
+  jobject ReleaseInternal();
+
+ private:
+  jobject obj_;
+
+  DISALLOW_COPY_AND_ASSIGN(JavaRef);
+};
+
+// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
+// for allowing functions to accept a reference without having to mandate
+// whether it is a local or global type.
+template<typename T>
+class JavaRef : public JavaRef<jobject> {
+ public:
+  T obj() const { return static_cast<T>(JavaRef<jobject>::obj()); }
+
+ protected:
+  JavaRef() {}
+  ~JavaRef() {}
+
+  JavaRef(JNIEnv* env, T obj) : JavaRef<jobject>(env, obj) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(JavaRef);
+};
+
+// Holds a local reference to a Java object. The local reference is scoped
+// to the lifetime of this object.
+// Instances of this class may hold onto any JNIEnv passed into it until
+// destroyed. Therefore, since a JNIEnv is only suitable for use on a single
+// thread, objects of this class must be created, used, and destroyed, on a
+// single thread.
+// Therefore, this class should only be used as a stack-based object and from a
+// single thread. If you wish to have the reference outlive the current
+// callstack (e.g. as a class member) or you wish to pass it across threads,
+// use a ScopedJavaGlobalRef instead.
+template<typename T>
+class ScopedJavaLocalRef : public JavaRef<T> {
+ public:
+  ScopedJavaLocalRef() : env_(NULL) {}
+
+  // Non-explicit copy constructor, to allow ScopedJavaLocalRef to be returned
+  // by value as this is the normal usage pattern.
+  ScopedJavaLocalRef(const ScopedJavaLocalRef<T>& other)
+      : env_(other.env_) {
+    this->SetNewLocalRef(env_, other.obj());
+  }
+
+  template<typename U>
+  explicit ScopedJavaLocalRef(const U& other)
+      : env_(NULL) {
+    this->Reset(other);
+  }
+
+  // Assumes that |obj| is a local reference to a Java object and takes
+  // ownership  of this local reference.
+  ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj), env_(env) {}
+
+  ~ScopedJavaLocalRef() {
+    this->Reset();
+  }
+
+  // Overloaded assignment operator defined for consistency with the implicit
+  // copy constructor.
+  void operator=(const ScopedJavaLocalRef<T>& other) {
+    this->Reset(other);
+  }
+
+  void Reset() {
+    this->ResetLocalRef(env_);
+  }
+
+  template<typename U>
+  void Reset(const ScopedJavaLocalRef<U>& other) {
+    // We can copy over env_ here as |other| instance must be from the same
+    // thread as |this| local ref. (See class comment for multi-threading
+    // limitations, and alternatives).
+    this->Reset(other.env_, other.obj());
+  }
+
+  template<typename U>
+  void Reset(const U& other) {
+    // If |env_| was not yet set (is still NULL) it will be attached to the
+    // current thread in SetNewLocalRef().
+    this->Reset(env_, other.obj());
+  }
+
+  template<typename U>
+  void Reset(JNIEnv* env, U obj) {
+    implicit_cast<T>(obj);  // Ensure U is assignable to T
+    env_ = this->SetNewLocalRef(env, obj);
+  }
+
+  // Releases the local reference to the caller. The caller *must* delete the
+  // local reference when it is done with it.
+  T Release() {
+    return static_cast<T>(this->ReleaseInternal());
+  }
+
+ private:
+  // This class is only good for use on the thread it was created on so
+  // it's safe to cache the non-threadsafe JNIEnv* inside this object.
+  JNIEnv* env_;
+};
+
+// Holds a global reference to a Java object. The global reference is scoped
+// to the lifetime of this object. This class does not hold onto any JNIEnv*
+// passed to it, hence it is safe to use across threads (within the constraints
+// imposed by the underlying Java object that it references).
+template<typename T>
+class ScopedJavaGlobalRef : public JavaRef<T> {
+ public:
+  ScopedJavaGlobalRef() {}
+
+  explicit ScopedJavaGlobalRef(const ScopedJavaGlobalRef<T>& other) {
+    this->Reset(other);
+  }
+
+  template<typename U>
+  explicit ScopedJavaGlobalRef(const U& other) {
+    this->Reset(other);
+  }
+
+  ~ScopedJavaGlobalRef() {
+    this->Reset();
+  }
+
+  void Reset() {
+    this->ResetGlobalRef();
+  }
+
+  template<typename U>
+  void Reset(const U& other) {
+    this->Reset(NULL, other.obj());
+  }
+
+  template<typename U>
+  void Reset(JNIEnv* env, U obj) {
+    implicit_cast<T>(obj);  // Ensure U is assignable to T
+    this->SetNewGlobalRef(env, obj);
+  }
+
+  // Releases the global reference to the caller. The caller *must* delete the
+  // global reference when it is done with it.
+  T Release() {
+    return static_cast<T>(this->ReleaseInternal());
+  }
+};
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_SCOPED_JAVA_REF_H_
diff --git a/src/base/android/scoped_java_ref_unittest.cc b/src/base/android/scoped_java_ref_unittest.cc
new file mode 100644
index 0000000..36f253c
--- /dev/null
+++ b/src/base/android/scoped_java_ref_unittest.cc
@@ -0,0 +1,122 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/scoped_java_ref.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace android {
+
+namespace {
+int g_local_refs = 0;
+int g_global_refs = 0;
+
+const JNINativeInterface* g_previous_functions;
+
+jobject NewGlobalRef(JNIEnv* env, jobject obj) {
+  ++g_global_refs;
+  return g_previous_functions->NewGlobalRef(env, obj);
+}
+
+void DeleteGlobalRef(JNIEnv* env, jobject obj) {
+  --g_global_refs;
+  return g_previous_functions->DeleteGlobalRef(env, obj);
+}
+
+jobject NewLocalRef(JNIEnv* env, jobject obj) {
+  ++g_local_refs;
+  return g_previous_functions->NewLocalRef(env, obj);
+}
+
+void DeleteLocalRef(JNIEnv* env, jobject obj) {
+  --g_local_refs;
+  return g_previous_functions->DeleteLocalRef(env, obj);
+}
+}  // namespace
+
+class ScopedJavaRefTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    g_local_refs = 0;
+    g_global_refs = 0;
+    JNIEnv* env = AttachCurrentThread();
+    g_previous_functions = env->functions;
+    hooked_functions = *g_previous_functions;
+    env->functions = &hooked_functions;
+    // We inject our own functions in JNINativeInterface so we can keep track
+    // of the reference counting ourselves.
+    hooked_functions.NewGlobalRef = &NewGlobalRef;
+    hooked_functions.DeleteGlobalRef = &DeleteGlobalRef;
+    hooked_functions.NewLocalRef = &NewLocalRef;
+    hooked_functions.DeleteLocalRef = &DeleteLocalRef;
+  }
+
+  virtual void TearDown() {
+    JNIEnv* env = AttachCurrentThread();
+    env->functions = g_previous_functions;
+  }
+  // From JellyBean release, the instance of this struct provided in JNIEnv is
+  // read-only, so we deep copy it to allow individual functions to be hooked.
+  JNINativeInterface hooked_functions;
+};
+
+// The main purpose of this is testing the various conversions compile.
+TEST_F(ScopedJavaRefTest, Conversions) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> str = ConvertUTF8ToJavaString(env, "string");
+  ScopedJavaGlobalRef<jstring> global(str);
+  {
+    ScopedJavaGlobalRef<jobject> global_obj(str);
+    ScopedJavaLocalRef<jobject> local_obj(global);
+    const JavaRef<jobject>& obj_ref1(str);
+    const JavaRef<jobject>& obj_ref2(global);
+    EXPECT_TRUE(env->IsSameObject(obj_ref1.obj(), obj_ref2.obj()));
+    EXPECT_TRUE(env->IsSameObject(global_obj.obj(), obj_ref2.obj()));
+  }
+  global.Reset(str);
+  const JavaRef<jstring>& str_ref = str;
+  EXPECT_EQ("string", ConvertJavaStringToUTF8(str_ref));
+  str.Reset();
+}
+
+TEST_F(ScopedJavaRefTest, RefCounts) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> str;
+  // The ConvertJavaStringToUTF8 below creates a new string that would normally
+  // return a local ref. We simulate that by starting the g_local_refs count at
+  // 1.
+  g_local_refs = 1;
+  str.Reset(ConvertUTF8ToJavaString(env, "string"));
+  EXPECT_EQ(1, g_local_refs);
+  EXPECT_EQ(0, g_global_refs);
+  {
+    ScopedJavaGlobalRef<jstring> global_str(str);
+    ScopedJavaGlobalRef<jobject> global_obj(global_str);
+    EXPECT_EQ(1, g_local_refs);
+    EXPECT_EQ(2, g_global_refs);
+
+    ScopedJavaLocalRef<jstring> str2(env, str.Release());
+    EXPECT_EQ(1, g_local_refs);
+    {
+      ScopedJavaLocalRef<jstring> str3(str2);
+      EXPECT_EQ(2, g_local_refs);
+    }
+    EXPECT_EQ(1, g_local_refs);
+    str2.Reset();
+    EXPECT_EQ(0, g_local_refs);
+    global_str.Reset();
+    EXPECT_EQ(1, g_global_refs);
+    ScopedJavaGlobalRef<jobject> global_obj2(global_obj);
+    EXPECT_EQ(2, g_global_refs);
+  }
+
+  EXPECT_EQ(0, g_local_refs);
+  EXPECT_EQ(0, g_global_refs);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/src/base/at_exit.cc b/src/base/at_exit.cc
new file mode 100644
index 0000000..0fba355
--- /dev/null
+++ b/src/base/at_exit.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+
+#include <stddef.h>
+#include <ostream>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+
+namespace base {
+
+// Keep a stack of registered AtExitManagers.  We always operate on the most
+// recent, and we should never have more than one outside of testing (for a
+// statically linked version of this library).  Testing may use the shadow
+// version of the constructor, and if we are building a dynamic library we may
+// end up with multiple AtExitManagers on the same process.  We don't protect
+// this for thread-safe access, since it will only be modified in testing.
+static AtExitManager* g_top_manager = NULL;
+
+AtExitManager::AtExitManager() : next_manager_(g_top_manager) {
+// If multiple modules instantiate AtExitManagers they'll end up living in this
+// module... they have to coexist.
+#if !defined(COMPONENT_BUILD)
+  DCHECK(!g_top_manager);
+#endif
+  g_top_manager = this;
+}
+
+AtExitManager::~AtExitManager() {
+  if (!g_top_manager) {
+    NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager";
+    return;
+  }
+  DCHECK_EQ(this, g_top_manager);
+
+  ProcessCallbacksNow();
+  g_top_manager = next_manager_;
+}
+
+// static
+void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) {
+  DCHECK(func);
+  RegisterTask(base::Bind(func, param));
+}
+
+// static
+void AtExitManager::RegisterTask(base::Closure task) {
+  if (!g_top_manager) {
+    NOTREACHED() << "Tried to RegisterCallback without an AtExitManager";
+    return;
+  }
+
+  AutoLock lock(g_top_manager->lock_);
+  g_top_manager->stack_.push(task);
+}
+
+// static
+void AtExitManager::ProcessCallbacksNow() {
+  if (!g_top_manager) {
+    NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager";
+    return;
+  }
+
+  AutoLock lock(g_top_manager->lock_);
+
+  while (!g_top_manager->stack_.empty()) {
+    base::Closure task = g_top_manager->stack_.top();
+    task.Run();
+    g_top_manager->stack_.pop();
+  }
+}
+
+AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
+  DCHECK(shadow || !g_top_manager);
+  g_top_manager = this;
+}
+
+}  // namespace base
diff --git a/src/base/at_exit.h b/src/base/at_exit.h
new file mode 100644
index 0000000..6b28ae9
--- /dev/null
+++ b/src/base/at_exit.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2011 The Chromium 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_AT_EXIT_H_
+#define BASE_AT_EXIT_H_
+
+#include <stack>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/synchronization/lock.h"
+
+namespace base {
+
+// This class provides a facility similar to the CRT atexit(), except that
+// we control when the callbacks are executed. Under Windows for a DLL they
+// happen at a really bad time and under the loader lock. This facility is
+// mostly used by base::Singleton.
+//
+// The usage is simple. Early in the main() or WinMain() scope create an
+// AtExitManager object on the stack:
+// int main(...) {
+//    base::AtExitManager exit_manager;
+//
+// }
+// When the exit_manager object goes out of scope, all the registered
+// callbacks and singleton destructors will be called.
+
+class BASE_EXPORT AtExitManager {
+ public:
+  typedef void (*AtExitCallbackType)(void*);
+
+  AtExitManager();
+
+  // The dtor calls all the registered callbacks. Do not try to register more
+  // callbacks after this point.
+  ~AtExitManager();
+
+  // Registers the specified function to be called at exit. The prototype of
+  // the callback function is void func(void*).
+  static void RegisterCallback(AtExitCallbackType func, void* param);
+
+  // Registers the specified task to be called at exit.
+  static void RegisterTask(base::Closure task);
+
+  // Calls the functions registered with RegisterCallback in LIFO order. It
+  // is possible to register new callbacks after calling this function.
+  static void ProcessCallbacksNow();
+
+ protected:
+  // This constructor will allow this instance of AtExitManager to be created
+  // even if one already exists.  This should only be used for testing!
+  // AtExitManagers are kept on a global stack, and it will be removed during
+  // destruction.  This allows you to shadow another AtExitManager.
+  explicit AtExitManager(bool shadow);
+
+ private:
+  base::Lock lock_;
+  std::stack<base::Closure> stack_;
+  AtExitManager* next_manager_;  // Stack of managers to allow shadowing.
+
+  DISALLOW_COPY_AND_ASSIGN(AtExitManager);
+};
+
+#if defined(__LB_SHELL__) || defined(UNIT_TEST) || defined(COBALT)
+class ShadowingAtExitManager : public AtExitManager {
+ public:
+  ShadowingAtExitManager() : AtExitManager(true) {}
+};
+#endif  // defined(UNIT_TEST)
+
+}  // namespace base
+
+#endif  // BASE_AT_EXIT_H_
diff --git a/src/base/at_exit_unittest.cc b/src/base/at_exit_unittest.cc
new file mode 100644
index 0000000..cda7340
--- /dev/null
+++ b/src/base/at_exit_unittest.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/bind.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+int g_test_counter_1 = 0;
+int g_test_counter_2 = 0;
+
+void IncrementTestCounter1(void* unused) {
+  ++g_test_counter_1;
+}
+
+void IncrementTestCounter2(void* unused) {
+  ++g_test_counter_2;
+}
+
+void ZeroTestCounters() {
+  g_test_counter_1 = 0;
+  g_test_counter_2 = 0;
+}
+
+void ExpectCounter1IsZero(void* unused) {
+  EXPECT_EQ(0, g_test_counter_1);
+}
+
+void ExpectParamIsNull(void* param) {
+  EXPECT_EQ(static_cast<void*>(NULL), param);
+}
+
+void ExpectParamIsCounter(void* param) {
+  EXPECT_EQ(&g_test_counter_1, param);
+}
+
+}  // namespace
+
+class AtExitTest : public testing::Test {
+ private:
+  // Don't test the global AtExitManager, because asking it to process its
+  // AtExit callbacks can ruin the global state that other tests may depend on.
+  base::ShadowingAtExitManager exit_manager_;
+};
+
+TEST_F(AtExitTest, Basic) {
+  ZeroTestCounters();
+  base::AtExitManager::RegisterCallback(&IncrementTestCounter1, NULL);
+  base::AtExitManager::RegisterCallback(&IncrementTestCounter2, NULL);
+  base::AtExitManager::RegisterCallback(&IncrementTestCounter1, NULL);
+
+  EXPECT_EQ(0, g_test_counter_1);
+  EXPECT_EQ(0, g_test_counter_2);
+  base::AtExitManager::ProcessCallbacksNow();
+  EXPECT_EQ(2, g_test_counter_1);
+  EXPECT_EQ(1, g_test_counter_2);
+}
+
+TEST_F(AtExitTest, LIFOOrder) {
+  ZeroTestCounters();
+  base::AtExitManager::RegisterCallback(&IncrementTestCounter1, NULL);
+  base::AtExitManager::RegisterCallback(&ExpectCounter1IsZero, NULL);
+  base::AtExitManager::RegisterCallback(&IncrementTestCounter2, NULL);
+
+  EXPECT_EQ(0, g_test_counter_1);
+  EXPECT_EQ(0, g_test_counter_2);
+  base::AtExitManager::ProcessCallbacksNow();
+  EXPECT_EQ(1, g_test_counter_1);
+  EXPECT_EQ(1, g_test_counter_2);
+}
+
+TEST_F(AtExitTest, Param) {
+  base::AtExitManager::RegisterCallback(&ExpectParamIsNull, NULL);
+  base::AtExitManager::RegisterCallback(&ExpectParamIsCounter,
+                                        &g_test_counter_1);
+  base::AtExitManager::ProcessCallbacksNow();
+}
+
+TEST_F(AtExitTest, Task) {
+  ZeroTestCounters();
+  base::AtExitManager::RegisterTask(base::Bind(&ExpectParamIsCounter,
+                                               &g_test_counter_1));
+  base::AtExitManager::ProcessCallbacksNow();
+}
diff --git a/src/base/atomic_ref_count.h b/src/base/atomic_ref_count.h
new file mode 100644
index 0000000..5130860
--- /dev/null
+++ b/src/base/atomic_ref_count.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2011 The Chromium 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_
+
+#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/src/base/atomic_sequence_num.h b/src/base/atomic_sequence_num.h
new file mode 100644
index 0000000..7bf2778
--- /dev/null
+++ b/src/base/atomic_sequence_num.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ATOMIC_SEQUENCE_NUM_H_
+#define BASE_ATOMIC_SEQUENCE_NUM_H_
+
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+
+namespace base {
+
+class AtomicSequenceNumber;
+
+// Static (POD) AtomicSequenceNumber that MUST be used in global scope (or
+// non-function scope) ONLY. This implementation does not generate any static
+// initializer.  Note that it does not implement any constructor which means
+// that its fields are not initialized except when it is stored in the global
+// data section (.data in ELF). If you want to allocate an atomic sequence
+// number on the stack (or heap), please use the AtomicSequenceNumber class
+// declared below.
+class StaticAtomicSequenceNumber {
+ public:
+  inline int GetNext() {
+    return static_cast<int>(
+        base::subtle::NoBarrier_AtomicIncrement(&seq_, 1) - 1);
+  }
+
+ private:
+  friend class AtomicSequenceNumber;
+
+  inline void Reset() {
+    base::subtle::Release_Store(&seq_, 0);
+  }
+
+  base::subtle::Atomic32 seq_;
+};
+
+// AtomicSequenceNumber that can be stored and used safely (i.e. its fields are
+// always initialized as opposed to StaticAtomicSequenceNumber declared above).
+// Please use StaticAtomicSequenceNumber if you want to declare an atomic
+// sequence number in the global scope.
+class AtomicSequenceNumber {
+ public:
+  AtomicSequenceNumber() {
+    seq_.Reset();
+  }
+
+  inline int GetNext() {
+    return seq_.GetNext();
+  }
+
+ private:
+  StaticAtomicSequenceNumber seq_;
+  DISALLOW_COPY_AND_ASSIGN(AtomicSequenceNumber);
+};
+
+}  // namespace base
+
+#endif  // BASE_ATOMIC_SEQUENCE_NUM_H_
diff --git a/src/base/atomicops.h b/src/base/atomicops.h
new file mode 100644
index 0000000..230a601
--- /dev/null
+++ b/src/base/atomicops.h
@@ -0,0 +1,169 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// 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_
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+
+#if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || defined(__LB_XB360__) || defined(__LB_XB1__)
+// windows.h #defines this (only on x64). This causes problems because the
+// public API also uses MemoryBarrier at the public name for this fence. So, on
+// X64, undef it, and call its documented
+// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
+// implementation directly.
+#undef MemoryBarrier
+#endif
+
+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(THREAD_SANITIZER)
+#include "base/atomicops_internals_tsan.h"
+#elif defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
+#include "base/atomicops_internals_x86_msvc.h"
+#elif defined(OS_MACOSX)
+#include "base/atomicops_internals_mac.h"
+#elif defined(OS_STARBOARD)
+#include "base/atomicops_internals_starboard.h"
+#elif defined(__LB_SHELL__)
+#define SHELL_BEGIN_ATOMICOPS_NAMESPACES namespace base { namespace subtle {
+#define SHELL_END_ATOMICOPS_NAMESPACES } }
+#include "atomicops_internals_shell.h"  // from the platform lib
+#elif (defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)) || \
+       defined(OS_NACL)
+#include "base/atomicops_internals_gcc.h"
+#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
+#include "base/atomicops_internals_x86_gcc.h"
+#elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS_FAMILY)
+#include "base/atomicops_internals_mips_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/src/base/atomicops_internals_atomicword_compat.h b/src/base/atomicops_internals_atomicword_compat.h
new file mode 100644
index 0000000..e02d11d
--- /dev/null
+++ b/src/base/atomicops_internals_atomicword_compat.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2011 The Chromium 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_
+
+// 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/src/base/atomicops_internals_gcc.h b/src/base/atomicops_internals_gcc.h
new file mode 100644
index 0000000..ed1b2d7
--- /dev/null
+++ b/src/base/atomicops_internals_gcc.h
@@ -0,0 +1,106 @@
+// 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, include base/atomicops.h
+// instead. This file is for platforms that use GCC intrinsics rather than
+// platform-specific assembly code for atomic operations.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_GCC_H_
+#define BASE_ATOMICOPS_INTERNALS_GCC_H_
+
+namespace base {
+namespace subtle {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value;
+  do {
+    if (__sync_bool_compare_and_swap(ptr, old_value, new_value))
+      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 (!__sync_bool_compare_and_swap(ptr, old_value, new_value));
+  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 (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
+      // 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) {
+  // Since NoBarrier_CompareAndSwap uses __sync_bool_compare_and_swap, which
+  // is a full memory barrier, none is needed here or below in Release.
+  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() {
+  __sync_synchronize();
+}
+
+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_GCC_H_
+
diff --git a/src/base/atomicops_internals_mac.h b/src/base/atomicops_internals_mac.h
new file mode 100644
index 0000000..658ed54
--- /dev/null
+++ b/src/base/atomicops_internals_mac.h
@@ -0,0 +1,197 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is an internal atomic implementation, use base/atomicops.h instead.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_MAC_H_
+#define BASE_ATOMICOPS_INTERNALS_MAC_H_
+
+#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_MAC_H_
diff --git a/src/base/atomicops_internals_mips_gcc.h b/src/base/atomicops_internals_mips_gcc.h
new file mode 100644
index 0000000..505597e
--- /dev/null
+++ b/src/base/atomicops_internals_mips_gcc.h
@@ -0,0 +1,161 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is an internal atomic implementation, use base/atomicops.h instead.
+//
+// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
+#define BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+namespace base {
+namespace subtle {
+
+// 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.
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev, tmp;
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "ll %0, %5\n"  // prev = *ptr
+                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
+                       "move %2, %4\n"  // tmp = new_value
+                       "sc %2, %1\n"  // *ptr = tmp (with atomic check)
+                       "beqz %2, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       "2:\n"
+                       ".set pop\n"
+                       : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
+                       : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+                       : "memory");
+  return prev;
+}
+
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 temp, old;
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "ll %1, %2\n"  // old = *ptr
+                       "move %0, %3\n"  // temp = new_value
+                       "sc %0, %2\n"  // *ptr = temp (with atomic check)
+                       "beqz %0, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       ".set pop\n"
+                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
+                       : "r" (new_value), "m" (*ptr)
+                       : "memory");
+
+  return old;
+}
+
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 temp, temp2;
+
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "ll %0, %2\n"  // temp = *ptr
+                       "addu %1, %0, %3\n"  // temp2 = temp + increment
+                       "sc %1, %2\n"  // *ptr = temp2 (with atomic check)
+                       "beqz %1, 1b\n"  // start again on atomic error
+                       "addu %1, %0, %3\n"  // temp2 = temp + increment
+                       ".set pop\n"
+                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
+                       : "Ir" (increment), "m" (*ptr)
+                       : "memory");
+  // temp2 now holds the final value.
+  return temp2;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  ATOMICOPS_COMPILER_BARRIER();
+  Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
+  ATOMICOPS_COMPILER_BARRIER();
+  return res;
+}
+
+// "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.
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ATOMICOPS_COMPILER_BARRIER();
+  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  ATOMICOPS_COMPILER_BARRIER();
+  return res;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ATOMICOPS_COMPILER_BARRIER();
+  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  ATOMICOPS_COMPILER_BARRIER();
+  return res;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() {
+  __asm__ __volatile__("sync" : : : "memory");
+}
+
+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
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
diff --git a/src/base/atomicops_internals_starboard.h b/src/base/atomicops_internals_starboard.h
new file mode 100644
index 0000000..cb1c759
--- /dev/null
+++ b/src/base/atomicops_internals_starboard.h
@@ -0,0 +1,151 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file is an internal atomic implementation, use base/atomicops.h instead.
+
+// This is the Starboard implementation, which defers all specific
+// implementation decisions for atomic operations to the Starboard port.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_STARBOARD_H_
+#define BASE_ATOMICOPS_INTERNALS_STARBOARD_H_
+
+#include "starboard/atomic.h"
+
+namespace base {
+namespace subtle {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  return SbAtomicNoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
+                                         Atomic32 new_value) {
+  return SbAtomicNoBarrier_Exchange(ptr, new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                          Atomic32 increment) {
+  return SbAtomicNoBarrier_Increment(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                        Atomic32 increment) {
+  return SbAtomicBarrier_Increment(ptr, increment);
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return SbAtomicAcquire_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return SbAtomicRelease_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  SbAtomicNoBarrier_Store(ptr, value);
+}
+
+inline void MemoryBarrier() {
+  SbAtomicMemoryBarrier();
+}
+
+inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  SbAtomicAcquire_Store(ptr, value);
+}
+
+inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  SbAtomicRelease_Store(ptr, value);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) {
+  return SbAtomicNoBarrier_Load(ptr);
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
+  return SbAtomicAcquire_Load(ptr);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+  return SbAtomicRelease_Load(ptr);
+}
+
+#if SB_IS(64_BIT)
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  return SbAtomicNoBarrier_CompareAndSwap64(ptr, old_value, new_value);
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
+                                         Atomic64 new_value) {
+  return SbAtomicNoBarrier_Exchange64(ptr, new_value);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                          Atomic64 increment) {
+  return SbAtomicNoBarrier_Increment64(ptr, increment);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                        Atomic64 increment) {
+  return SbAtomicBarrier_Increment64(ptr, increment);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return SbAtomicAcquire_CompareAndSwap64(ptr, old_value, new_value);
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return SbAtomicRelease_CompareAndSwap64(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  SbAtomicNoBarrier_Store64(ptr, value);
+}
+
+inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  SbAtomicAcquire_Store64(ptr, value);
+}
+
+inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  SbAtomicRelease_Store64(ptr, value);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) {
+  return SbAtomicNoBarrier_Load64(ptr);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
+  return SbAtomicAcquire_Load64(ptr);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+  return SbAtomicRelease_Load64(ptr);
+}
+#endif  // SB_IS(64_BIT)
+
+}  // namespace base::subtle
+}  // namespace base
+
+#endif  // BASE_ATOMICOPS_INTERNALS_STARBOARD_H_
diff --git a/src/base/atomicops_internals_tsan.h b/src/base/atomicops_internals_tsan.h
new file mode 100644
index 0000000..44d6400
--- /dev/null
+++ b/src/base/atomicops_internals_tsan.h
@@ -0,0 +1,378 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is an internal atomic implementation for compiler-based
+// ThreadSanitizer. Use base/atomicops.h instead.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_TSAN_H_
+#define BASE_ATOMICOPS_INTERNALS_TSAN_H_
+
+#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 {
+
+#ifndef TSAN_INTERFACE_ATOMIC_H
+#define TSAN_INTERFACE_ATOMIC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef char  __tsan_atomic8;
+typedef short __tsan_atomic16;  // NOLINT
+typedef int   __tsan_atomic32;
+typedef long  __tsan_atomic64;  // NOLINT
+
+#if defined(__SIZEOF_INT128__) \
+    || (__clang_major__ * 100 + __clang_minor__ >= 302)
+typedef __int128 __tsan_atomic128;
+#define __TSAN_HAS_INT128 1
+#else
+typedef char     __tsan_atomic128;
+#define __TSAN_HAS_INT128 0
+#endif
+
+typedef enum {
+  __tsan_memory_order_relaxed,
+  __tsan_memory_order_consume,
+  __tsan_memory_order_acquire,
+  __tsan_memory_order_release,
+  __tsan_memory_order_acq_rel,
+  __tsan_memory_order_seq_cst,
+} __tsan_memory_order;
+
+__tsan_atomic8 __tsan_atomic8_load(const volatile __tsan_atomic8 *a,
+    __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_load(const volatile __tsan_atomic16 *a,
+    __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_load(const volatile __tsan_atomic32 *a,
+    __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_load(const volatile __tsan_atomic64 *a,
+    __tsan_memory_order mo);
+__tsan_atomic128 __tsan_atomic128_load(const volatile __tsan_atomic128 *a,
+    __tsan_memory_order mo);
+
+void __tsan_atomic8_store(volatile __tsan_atomic8 *a, __tsan_atomic8 v,
+    __tsan_memory_order mo);
+void __tsan_atomic16_store(volatile __tsan_atomic16 *a, __tsan_atomic16 v,
+    __tsan_memory_order mo);
+void __tsan_atomic32_store(volatile __tsan_atomic32 *a, __tsan_atomic32 v,
+    __tsan_memory_order mo);
+void __tsan_atomic64_store(volatile __tsan_atomic64 *a, __tsan_atomic64 v,
+    __tsan_memory_order mo);
+void __tsan_atomic128_store(volatile __tsan_atomic128 *a, __tsan_atomic128 v,
+    __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_exchange(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_exchange(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_exchange(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 v, __tsan_memory_order mo);
+__tsan_atomic128 __tsan_atomic128_exchange(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 v, __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_fetch_add(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_add(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_add(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_add(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 v, __tsan_memory_order mo);
+__tsan_atomic128 __tsan_atomic128_fetch_add(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 v, __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_fetch_and(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_and(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_and(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_and(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 v, __tsan_memory_order mo);
+__tsan_atomic128 __tsan_atomic128_fetch_and(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 v, __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_fetch_or(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_or(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_or(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_or(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 v, __tsan_memory_order mo);
+__tsan_atomic128 __tsan_atomic128_fetch_or(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 v, __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_fetch_xor(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_xor(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_xor(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_xor(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 v, __tsan_memory_order mo);
+__tsan_atomic128 __tsan_atomic128_fetch_xor(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 v, __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_fetch_nand(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_nand(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_nand(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_nand(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 v, __tsan_memory_order mo);
+__tsan_atomic128 __tsan_atomic128_fetch_nand(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 v, __tsan_memory_order mo);
+
+int __tsan_atomic8_compare_exchange_weak(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic16_compare_exchange_weak(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic32_compare_exchange_weak(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic64_compare_exchange_weak(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic128_compare_exchange_weak(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+
+int __tsan_atomic8_compare_exchange_strong(volatile __tsan_atomic8 *a,
+    __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic16_compare_exchange_strong(volatile __tsan_atomic16 *a,
+    __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic32_compare_exchange_strong(volatile __tsan_atomic32 *a,
+    __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic64_compare_exchange_strong(volatile __tsan_atomic64 *a,
+    __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+int __tsan_atomic128_compare_exchange_strong(volatile __tsan_atomic128 *a,
+    __tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo,
+    __tsan_memory_order fail_mo);
+
+__tsan_atomic8 __tsan_atomic8_compare_exchange_val(
+    volatile __tsan_atomic8 *a, __tsan_atomic8 c, __tsan_atomic8 v,
+    __tsan_memory_order mo, __tsan_memory_order fail_mo);
+__tsan_atomic16 __tsan_atomic16_compare_exchange_val(
+    volatile __tsan_atomic16 *a, __tsan_atomic16 c, __tsan_atomic16 v,
+    __tsan_memory_order mo, __tsan_memory_order fail_mo);
+__tsan_atomic32 __tsan_atomic32_compare_exchange_val(
+    volatile __tsan_atomic32 *a, __tsan_atomic32 c, __tsan_atomic32 v,
+    __tsan_memory_order mo, __tsan_memory_order fail_mo);
+__tsan_atomic64 __tsan_atomic64_compare_exchange_val(
+    volatile __tsan_atomic64 *a, __tsan_atomic64 c, __tsan_atomic64 v,
+    __tsan_memory_order mo, __tsan_memory_order fail_mo);
+__tsan_atomic128 __tsan_atomic128_compare_exchange_val(
+    volatile __tsan_atomic128 *a, __tsan_atomic128 c, __tsan_atomic128 v,
+    __tsan_memory_order mo, __tsan_memory_order fail_mo);
+
+void __tsan_atomic_thread_fence(__tsan_memory_order mo);
+void __tsan_atomic_signal_fence(__tsan_memory_order mo);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // #ifndef TSAN_INTERFACE_ATOMIC_H
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
+                                  Atomic32 old_value,
+                                  Atomic32 new_value) {
+  Atomic32 cmp = old_value;
+  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
+                                  Atomic32 new_value) {
+  return __tsan_atomic32_exchange(ptr, new_value,
+      __tsan_memory_order_relaxed);
+}
+
+inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr,
+                                Atomic32 new_value) {
+  return __tsan_atomic32_exchange(ptr, new_value,
+      __tsan_memory_order_acquire);
+}
+
+inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr,
+                                Atomic32 new_value) {
+  return __tsan_atomic32_exchange(ptr, new_value,
+      __tsan_memory_order_release);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                   Atomic32 increment) {
+  return increment + __tsan_atomic32_fetch_add(ptr, increment,
+      __tsan_memory_order_relaxed);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                 Atomic32 increment) {
+  return increment + __tsan_atomic32_fetch_add(ptr, increment,
+      __tsan_memory_order_acq_rel);
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value) {
+  Atomic32 cmp = old_value;
+  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_acquire, __tsan_memory_order_acquire);
+  return cmp;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value) {
+  Atomic32 cmp = old_value;
+  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_release, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+}
+
+inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  __tsan_atomic32_store(ptr, value, __tsan_memory_order_release);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) {
+  return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
+  return __tsan_atomic32_load(ptr, __tsan_memory_order_acquire);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+  return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
+                                      Atomic64 old_value,
+                                      Atomic64 new_value) {
+  Atomic64 cmp = old_value;
+  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
+                                      Atomic64 new_value) {
+  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr,
+                                    Atomic64 new_value) {
+  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_acquire);
+}
+
+inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr,
+                                    Atomic64 new_value) {
+  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_release);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                       Atomic64 increment) {
+  return increment + __tsan_atomic64_fetch_add(ptr, increment,
+      __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                     Atomic64 increment) {
+  return increment + __tsan_atomic64_fetch_add(ptr, increment,
+      __tsan_memory_order_acq_rel);
+}
+
+inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+}
+
+inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  __tsan_atomic64_store(ptr, value, __tsan_memory_order_release);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) {
+  return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
+  return __tsan_atomic64_load(ptr, __tsan_memory_order_acquire);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+  return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
+                                    Atomic64 old_value,
+                                    Atomic64 new_value) {
+  Atomic64 cmp = old_value;
+  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_acquire, __tsan_memory_order_acquire);
+  return cmp;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
+                                    Atomic64 old_value,
+                                    Atomic64 new_value) {
+  Atomic64 cmp = old_value;
+  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_release, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline void MemoryBarrier() {
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+}
+
+}  // namespace base::subtle
+}  // namespace base
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // BASE_ATOMICOPS_INTERNALS_TSAN_H_
diff --git a/src/base/atomicops_internals_x86_gcc.cc b/src/base/atomicops_internals_x86_gcc.cc
new file mode 100644
index 0000000..933ca51
--- /dev/null
+++ b/src/base/atomicops_internals_x86_gcc.cc
@@ -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/src/base/atomicops_internals_x86_gcc.h b/src/base/atomicops_internals_x86_gcc.h
new file mode 100644
index 0000000..ac02b17
--- /dev/null
+++ b/src/base/atomicops_internals_x86_gcc.h
@@ -0,0 +1,269 @@
+// Copyright (c) 2011 The Chromium 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_
+
+#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/src/base/atomicops_internals_x86_msvc.h b/src/base/atomicops_internals_x86_msvc.h
new file mode 100644
index 0000000..2f428b6
--- /dev/null
+++ b/src/base/atomicops_internals_x86_msvc.h
@@ -0,0 +1,224 @@
+// 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_
+
+#if defined(__LB_XB1__) && !defined(WIN32)
+# include <intrin.h>
+// These are normally defined by windows.h:
+typedef long LONG;
+typedef long long LONGLONG;
+typedef void* PVOID;
+void __faststorefence(void);
+#pragma intrinsic(__faststorefence)
+inline void MemoryBarrier() {
+  __faststorefence();
+}
+#define InterlockedCompareExchange _InterlockedCompareExchange
+#define InterlockedCompareExchangePointer _InterlockedCompareExchangePointer
+#define InterlockedExchangePointer _InterlockedExchangePointer
+#define InterlockedExchange _InterlockedExchange
+#define InterlockedExchangeAdd _InterlockedExchangeAdd
+#define InterlockedExchangeAdd64 _InterlockedExchangeAdd64
+
+#else
+# include <windows.h>
+
+#if defined(ARCH_CPU_64_BITS) || defined(__LB_XB360__)
+// windows.h #defines this (only on x64). This causes problems because the
+// public API also uses MemoryBarrier at the public name for this fence. So, on
+// X64, undef it, and call its documented
+// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
+// implementation directly.
+#undef MemoryBarrier
+#endif
+
+#endif
+
+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() {
+#if defined(ARCH_CPU_64_BITS) || defined(__LB_XB360__)
+  // See #undef and note at the top of this file.
+  __faststorefence();
+#else
+  // We use MemoryBarrier from WinNT.h
+  ::MemoryBarrier();
+#endif
+}
+
+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
+
+#if defined(__LB_XB1__)
+#undef InterlockedCompareExchange
+#undef InterlockedCompareExchangePointer
+#undef InterlockedExchangePointer
+#undef InterlockedExchange
+#undef InterlockedExchangeAdd
+#undef InterlockedExchangeAdd64
+#endif
+
+#endif  // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
diff --git a/src/base/atomicops_unittest.cc b/src/base/atomicops_unittest.cc
new file mode 100644
index 0000000..d73a098
--- /dev/null
+++ b/src/base/atomicops_unittest.cc
@@ -0,0 +1,241 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/atomicops.h"
+
+#include <string.h>
+
+#include "base/port.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+template <class AtomicType>
+static void TestAtomicIncrement() {
+  // For now, we just test single threaded execution
+
+  // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
+  // outside the expected address bounds.  This is in particular to
+  // test that some future change to the asm code doesn't cause the
+  // 32-bit NoBarrier_AtomicIncrement doesn't do the wrong thing on 64-bit
+  // machines.
+  struct {
+    AtomicType prev_word;
+    AtomicType count;
+    AtomicType next_word;
+  } s;
+
+  AtomicType prev_word_value, next_word_value;
+  memset(&prev_word_value, 0xFF, sizeof(AtomicType));
+  memset(&next_word_value, 0xEE, sizeof(AtomicType));
+
+  s.prev_word = prev_word_value;
+  s.count = 0;
+  s.next_word = next_word_value;
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
+  EXPECT_EQ(s.count, 1);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
+  EXPECT_EQ(s.count, 3);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
+  EXPECT_EQ(s.count, 6);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
+  EXPECT_EQ(s.count, 3);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
+  EXPECT_EQ(s.count, 1);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
+  EXPECT_EQ(s.count, 0);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
+  EXPECT_EQ(s.count, -1);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
+  EXPECT_EQ(s.count, -5);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+
+  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
+  EXPECT_EQ(s.count, 0);
+  EXPECT_EQ(s.prev_word, prev_word_value);
+  EXPECT_EQ(s.next_word, next_word_value);
+}
+
+
+#define NUM_BITS(T) (sizeof(T) * 8)
+
+
+template <class AtomicType>
+static void TestCompareAndSwap() {
+  AtomicType value = 0;
+  AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
+  EXPECT_EQ(1, value);
+  EXPECT_EQ(0, prev);
+
+  // Use test value that has non-zero bits in both halves, more for testing
+  // 64-bit implementation on 32-bit platforms.
+  const AtomicType k_test_val = (GG_ULONGLONG(1) <<
+                                 (NUM_BITS(AtomicType) - 2)) + 11;
+  value = k_test_val;
+  prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
+  EXPECT_EQ(k_test_val, value);
+  EXPECT_EQ(k_test_val, prev);
+
+  value = k_test_val;
+  prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
+  EXPECT_EQ(5, value);
+  EXPECT_EQ(k_test_val, prev);
+}
+
+
+template <class AtomicType>
+static void TestAtomicExchange() {
+  AtomicType value = 0;
+  AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
+  EXPECT_EQ(1, value);
+  EXPECT_EQ(0, new_value);
+
+  // Use test value that has non-zero bits in both halves, more for testing
+  // 64-bit implementation on 32-bit platforms.
+  const AtomicType k_test_val = (GG_ULONGLONG(1) <<
+                                 (NUM_BITS(AtomicType) - 2)) + 11;
+  value = k_test_val;
+  new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
+  EXPECT_EQ(k_test_val, value);
+  EXPECT_EQ(k_test_val, new_value);
+
+  value = k_test_val;
+  new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
+  EXPECT_EQ(5, value);
+  EXPECT_EQ(k_test_val, new_value);
+}
+
+
+template <class AtomicType>
+static void TestAtomicIncrementBounds() {
+  // Test at rollover boundary between int_max and int_min
+  AtomicType test_val = (GG_ULONGLONG(1) <<
+                         (NUM_BITS(AtomicType) - 1));
+  AtomicType value = -1 ^ test_val;
+  AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
+  EXPECT_EQ(test_val, value);
+  EXPECT_EQ(value, new_value);
+
+  base::subtle::NoBarrier_AtomicIncrement(&value, -1);
+  EXPECT_EQ(-1 ^ test_val, value);
+
+  // Test at 32-bit boundary for 64-bit atomic type.
+  test_val = GG_ULONGLONG(1) << (NUM_BITS(AtomicType) / 2);
+  value = test_val - 1;
+  new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
+  EXPECT_EQ(test_val, value);
+  EXPECT_EQ(value, new_value);
+
+  base::subtle::NoBarrier_AtomicIncrement(&value, -1);
+  EXPECT_EQ(test_val - 1, value);
+}
+
+// Return an AtomicType with the value 0xa5a5a5..
+template <class AtomicType>
+static AtomicType TestFillValue() {
+  AtomicType val = 0;
+  memset(&val, 0xa5, sizeof(AtomicType));
+  return val;
+}
+
+// This is a simple sanity check that values are correct. Not testing
+// atomicity
+template <class AtomicType>
+static void TestStore() {
+  const AtomicType kVal1 = TestFillValue<AtomicType>();
+  const AtomicType kVal2 = static_cast<AtomicType>(-1);
+
+  AtomicType value;
+
+  base::subtle::NoBarrier_Store(&value, kVal1);
+  EXPECT_EQ(kVal1, value);
+  base::subtle::NoBarrier_Store(&value, kVal2);
+  EXPECT_EQ(kVal2, value);
+
+  base::subtle::Acquire_Store(&value, kVal1);
+  EXPECT_EQ(kVal1, value);
+  base::subtle::Acquire_Store(&value, kVal2);
+  EXPECT_EQ(kVal2, value);
+
+  base::subtle::Release_Store(&value, kVal1);
+  EXPECT_EQ(kVal1, value);
+  base::subtle::Release_Store(&value, kVal2);
+  EXPECT_EQ(kVal2, value);
+}
+
+// This is a simple sanity check that values are correct. Not testing
+// atomicity
+template <class AtomicType>
+static void TestLoad() {
+  const AtomicType kVal1 = TestFillValue<AtomicType>();
+  const AtomicType kVal2 = static_cast<AtomicType>(-1);
+
+  AtomicType value;
+
+  value = kVal1;
+  EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
+  value = kVal2;
+  EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
+
+  value = kVal1;
+  EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
+  value = kVal2;
+  EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
+
+  value = kVal1;
+  EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
+  value = kVal2;
+  EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
+}
+
+TEST(AtomicOpsTest, Inc) {
+  TestAtomicIncrement<base::subtle::Atomic32>();
+  TestAtomicIncrement<base::subtle::AtomicWord>();
+}
+
+TEST(AtomicOpsTest, CompareAndSwap) {
+  TestCompareAndSwap<base::subtle::Atomic32>();
+  TestCompareAndSwap<base::subtle::AtomicWord>();
+}
+
+TEST(AtomicOpsTest, Exchange) {
+  TestAtomicExchange<base::subtle::Atomic32>();
+  TestAtomicExchange<base::subtle::AtomicWord>();
+}
+
+TEST(AtomicOpsTest, IncrementBounds) {
+  TestAtomicIncrementBounds<base::subtle::Atomic32>();
+  TestAtomicIncrementBounds<base::subtle::AtomicWord>();
+}
+
+TEST(AtomicOpsTest, Store) {
+  TestStore<base::subtle::Atomic32>();
+  TestStore<base::subtle::AtomicWord>();
+}
+
+TEST(AtomicOpsTest, Load) {
+  TestLoad<base::subtle::Atomic32>();
+  TestLoad<base::subtle::AtomicWord>();
+}
diff --git a/src/base/auto_reset.h b/src/base/auto_reset.h
new file mode 100644
index 0000000..32f138e
--- /dev/null
+++ b/src/base/auto_reset.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2011 The Chromium 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_AUTO_RESET_H_
+#define BASE_AUTO_RESET_H_
+
+#include "base/basictypes.h"
+
+// base::AutoReset<> is useful for setting a variable to a new value only within
+// a particular scope. An base::AutoReset<> object resets a variable to its
+// original value upon destruction, making it an alternative to writing
+// "var = false;" or "var = old_val;" at all of a block's exit points.
+//
+// This should be obvious, but note that an base::AutoReset<> instance should
+// have a shorter lifetime than its scoped_variable, to prevent invalid memory
+// writes when the base::AutoReset<> object is destroyed.
+
+namespace base {
+
+template<typename T>
+class AutoReset {
+ public:
+  AutoReset(T* scoped_variable, T new_value)
+      : scoped_variable_(scoped_variable),
+        original_value_(*scoped_variable) {
+    *scoped_variable_ = new_value;
+  }
+
+  ~AutoReset() { *scoped_variable_ = original_value_; }
+
+ private:
+  T* scoped_variable_;
+  T original_value_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoReset);
+};
+
+}
+
+#endif  // BASE_AUTO_RESET_H_
diff --git a/src/base/base.gyp b/src/base/base.gyp
new file mode 100644
index 0000000..3838ff6
--- /dev/null
+++ b/src/base/base.gyp
@@ -0,0 +1,1322 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'includes': [
+    '../build/win_precompile.gypi',
+    'base.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'base',
+      'type': '<(component)',
+      'toolsets': ['host', 'target'],
+      'variables': {
+        'base_target': 1,
+        'enable_wexit_time_destructors': 1,
+        'optimize': 'max',
+      },
+      'dependencies': [
+        'base_static',
+        'allocator/allocator.gyp:allocator_extension_thunks',
+        '../testing/gtest.gyp:gtest_prod',
+        '../third_party/modp_b64/modp_b64.gyp:modp_b64',
+        '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': [
+        ['use_glib==1', {
+          'conditions': [
+            ['chromeos==1', {
+              'sources/': [ ['include', '_chromeos\\.cc$'] ]
+            }],
+            ['linux_use_tcmalloc==0', {
+              'defines': [
+                'NO_TCMALLOC',
+              ],
+              'direct_dependent_settings': {
+                'defines': [
+                  'NO_TCMALLOC',
+                ],
+              },
+            }],
+            ['toolkit_uses_gtk==1', {
+              'dependencies': [
+                '../build/linux/system.gyp:gtk',
+              ],
+              'export_dependent_settings': [
+                '../build/linux/system.gyp:gtk',
+              ],
+            }],
+          ],
+          'dependencies': [
+            'symbolize',
+            '../build/linux/system.gyp:glib',
+            '../build/linux/system.gyp:x11',
+            'xdg_mime',
+          ],
+          'defines': [
+            'USE_SYMBOLIZE',
+          ],
+          'cflags': [
+            '-Wno-write-strings',
+          ],
+          'export_dependent_settings': [
+            '../build/linux/system.gyp:glib',
+            '../build/linux/system.gyp:x11',
+          ],
+        }, {  # use_glib!=1
+            'sources/': [
+              ['exclude', '/xdg_user_dirs/'],
+              ['exclude', '_nss\\.cc$'],
+            ],
+        }],
+        ['OS == "android" and _toolset == "host"', {
+          # Base for host support is the minimum required to run the
+          # ssl false start blacklist tool. It requires further changes
+          # to generically support host builds (and tests).
+          # Note: when building for host, gyp has OS == "android",
+          # hence the *_android.cc files are included but the actual code
+          # doesn't have OS_ANDROID / ANDROID defined.
+          'conditions': [
+            # Host build on linux depends on system.gyp::gtk as
+            # default linux build has TOOLKIT_GTK defined.
+            ['host_os == "linux"', {
+              'sources/': [
+                ['include', '^atomicops_internals_x86_gcc\\.cc$'],
+              ],
+              'dependencies': [
+                '../build/linux/system.gyp:gtk',
+              ],
+              'export_dependent_settings': [
+                '../build/linux/system.gyp:gtk',
+              ],
+            }],
+            ['host_os == "mac"', {
+              'sources/': [
+                ['exclude', '^native_library_linux\\.cc$'],
+                ['exclude', '^process_util_linux\\.cc$'],
+                ['exclude', '^sys_info_linux\\.cc$'],
+                ['exclude', '^sys_string_conversions_linux\\.cc$'],
+                ['exclude', '^worker_pool_linux\\.cc$'],
+              ],
+            }],
+          ],
+        }],
+        ['(OS == "android" or ((OS == "lb_shell" or OS == "starboard") and target_arch == "android")) and _toolset == "target"', {
+          'dependencies': [
+            'base_jni_headers',
+            'symbolize',
+            '../third_party/ashmem/ashmem.gyp:ashmem',
+            '../third_party/icu/icu.gyp:icuuc',
+          ],
+          'include_dirs': [
+            '<(SHARED_INTERMEDIATE_DIR)/base',
+          ],
+          'link_settings': {
+            'libraries': [
+              '-llog',
+            ],
+          },
+          'defines': [
+            'USE_SYMBOLIZE',
+          ],
+          'sources!': [
+            'debug/stack_trace_posix.cc',
+          ],
+          'conditions' : [
+            ['target_arch == "ia32"', {
+              'sources/': [
+                ['include', '^atomicops_internals_x86_gcc\\.cc$'],
+              ],
+            }],
+            ['target_arch != "android"', {
+              'includes': [
+                '../build/android/cpufeatures.gypi',
+              ],
+            }],
+          ],
+        }],
+        ['(OS == "android" or ((OS == "lb_shell" or OS == "starboard") and target_arch == "android")) and _toolset == "target" and android_build_type == 0', {
+          'dependencies': [
+            'base_java',
+          ],
+        }],
+        ['((OS == "lb_shell" or OS == "starboard") and target_arch == "android")', {
+          'link_settings': {
+            'libraries': [
+              # for android_getCpuCount
+              '-lportable',
+            ],
+          },
+        }],
+        ['os_bsd==1', {
+          'include_dirs': [
+            '/usr/local/include',
+          ],
+          'link_settings': {
+            'libraries': [
+              '-L/usr/local/lib -lexecinfo',
+            ],
+          },
+        }],
+        ['OS == "linux"', {
+          'link_settings': {
+            'libraries': [
+              # We need rt for clock_gettime().
+              '-lrt',
+              # For 'native_library_linux.cc'
+              '-ldl',
+            ],
+          },
+        }],
+        ['OS == "mac"', {
+          'link_settings': {
+            'libraries': [
+              '$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
+              '$(SDKROOT)/System/Library/Frameworks/ApplicationServices.framework',
+              '$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
+              '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+              '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+              '$(SDKROOT)/System/Library/Frameworks/IOKit.framework',
+              '$(SDKROOT)/System/Library/Frameworks/Security.framework',
+            ],
+          },
+          'dependencies': [
+            '../third_party/mach_override/mach_override.gyp:mach_override',
+          ],
+        }],
+        ['OS == "ios"', {
+          'link_settings': {
+            'libraries': [
+              '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+              '$(SDKROOT)/System/Library/Frameworks/CoreGraphics.framework',
+              '$(SDKROOT)/System/Library/Frameworks/CoreText.framework',
+              '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+              '$(SDKROOT)/System/Library/Frameworks/UIKit.framework',
+            ],
+          },
+        }],
+        ['OS != "win" and OS != "ios"', {
+            'dependencies': ['../third_party/libevent/libevent.gyp:libevent'],
+        },],
+        ['component=="shared_library"', {
+          'conditions': [
+            ['OS=="win"', {
+              'sources!': [
+                'debug/debug_on_start_win.cc',
+              ],
+            }],
+          ],
+        }],
+        ['OS == "lb_shell"', {
+          'conditions': [
+            ['target_arch != "android"', {
+              'dependencies!': [
+                '../third_party/libevent/libevent.gyp:libevent'
+              ],
+            }],
+            ['target_arch == "linux"', {
+              'defines': [
+                'USE_SYMBOLIZE',
+              ],
+              'dependencies': [
+                'symbolize',
+              ],
+            }],
+            ['target_arch == "ps3" and _toolset == "target"', {
+              # Script for resolving symbols, for use by stack_trace_ps3.cc
+              'copies': [
+                {
+                  'destination': '<(PRODUCT_DIR)',
+                  'files': [
+                    'debug/addr2line_ps3.py',
+                  ],
+                },
+              ],
+              'dependencies': [
+                # On PS3, we use both posix emulation and starboard for
+                # threading.  We depend on starboard for its TLS implementation.
+                # Eventually this will replace the posix_emulation below.
+                '<(DEPTH)/starboard/starboard.gyp:starboard',
+              ],
+            }],
+            # toolset can be host or target.
+            # (host in the case of e.g. protobuf compiler.)
+            # We only want posix_emulation for target builds.
+            ['_toolset == "target"', {
+              'dependencies': [
+                '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
+              ],
+            }],  # _toolset == "target"
+          ],
+          'sources': [
+            'debug/debugger_shell.cc',
+            'debug/stack_trace_shell.cc',
+            'guid_shell.cc',
+            'safe_strerror_shell.cc',
+            'sys_string_conversions_shell.cc',
+            'test/test_file_util_shell.cc',
+            'threading/thread_local_shell.cc',
+            'threading/thread_local_storage_shell.cc',
+            'threading/worker_pool_shell.cc',
+          ],
+        }],  # OS=="lb_shell"
+        ['OS == "starboard"', {
+          'conditions': [
+            ['_toolset == "target"', {
+              'dependencies': [
+                '<(DEPTH)/starboard/starboard.gyp:starboard',
+                '<(DEPTH)/starboard/client_porting/eztime/eztime.gyp:eztime',
+               ],
+            }],  # _toolset == "target"
+          ],
+          'dependencies!': [
+            '../third_party/libevent/libevent.gyp:libevent'
+          ],
+          'sources': [
+            'base_paths_starboard.cc',
+            'test/test_file_util_starboard.cc',
+          ],
+        }],  # OS=="starboard"
+        ['OS == "lb_shell" or OS == "starboard"', {
+          'sources!': [
+            'file_descriptor_shuffle.cc',
+          ],
+        }],  # OS == "lb_shell" or OS == "starboard"
+      ],
+      'sources': [
+        'third_party/nspr/prcpucfg.h',
+        'third_party/nspr/prcpucfg_win.h',
+        'third_party/nspr/prtypes.h',
+        'third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
+        'third_party/xdg_user_dirs/xdg_user_dir_lookup.h',
+        'auto_reset.h',
+        'event_recorder.h',
+        'event_recorder_stubs.cc',
+        'event_recorder_win.cc',
+        'linux_util.cc',
+        'linux_util.h',
+        'md5.cc',
+        'md5.h',
+        'message_pump_android.cc',
+        'message_pump_android.h',
+        'message_pump_glib.cc',
+        'message_pump_glib.h',
+        'message_pump_gtk.cc',
+        'message_pump_gtk.h',
+        'message_pump_io_ios.cc',
+        'message_pump_io_ios.h',
+        'message_pump_observer.h',
+        'message_pump_aurax11.cc',
+        'message_pump_aurax11.h',
+        'message_pump_libevent.cc',
+        'message_pump_libevent.h',
+        'message_pump_mac.h',
+        'message_pump_mac.mm',
+        'metrics/field_trial.cc',
+        'metrics/field_trial.h',
+        'posix/file_descriptor_shuffle.cc',
+        'posix/file_descriptor_shuffle.h',
+        'sync_socket.h',
+        'sync_socket_win.cc',
+        'sync_socket_posix.cc',
+      ],
+    },
+    {
+      'target_name': 'base_i18n',
+      'type': '<(component)',
+      'variables': {
+        'enable_wexit_time_destructors': 1,
+        'optimize': 'max',
+      },
+      'dependencies': [
+        'base',
+        'third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../third_party/icu/icu.gyp:icui18n',
+        '../third_party/icu/icu.gyp:icuuc',
+      ],
+      'conditions': [
+        ['toolkit_uses_gtk==1', {
+          'dependencies': [
+            # i18n/rtl.cc uses gtk
+            '../build/linux/system.gyp:gtk',
+          ],
+        }],
+        ['OS=="lb_shell"', {
+          'dependencies': [
+            '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
+          ],
+        }],
+        ['OS=="starboard"', {
+          'dependencies': [
+            '<(DEPTH)/starboard/starboard.gyp:starboard',
+            '<(DEPTH)/starboard/client_porting/icu_init/icu_init.gyp:icu_init',
+          ],
+        }],
+      ],
+      'export_dependent_settings': [
+        'base',
+      ],
+      'defines': [
+        'BASE_I18N_IMPLEMENTATION',
+      ],
+      'sources': [
+        'i18n/base_i18n_export.h',
+        'i18n/bidi_line_iterator.cc',
+        'i18n/bidi_line_iterator.h',
+        'i18n/break_iterator.cc',
+        'i18n/break_iterator.h',
+        'i18n/char_iterator.cc',
+        'i18n/char_iterator.h',
+        'i18n/case_conversion.cc',
+        'i18n/case_conversion.h',
+        'i18n/file_util_icu.cc',
+        'i18n/file_util_icu.h',
+        'i18n/icu_encoding_detection.cc',
+        'i18n/icu_encoding_detection.h',
+        'i18n/icu_string_conversions.cc',
+        'i18n/icu_string_conversions.h',
+        'i18n/icu_util.cc',
+        'i18n/icu_util.h',
+        'i18n/number_formatting.cc',
+        'i18n/number_formatting.h',
+        'i18n/rtl.cc',
+        'i18n/rtl.h',
+        'i18n/string_search.cc',
+        'i18n/string_search.h',
+        'i18n/time_formatting.cc',
+        'i18n/time_formatting.h',
+      ],
+    },
+    {
+      'target_name': 'base_prefs',
+      'type': '<(component)',
+      'variables': {
+        'enable_wexit_time_destructors': 1,
+        'optimize': 'max',
+      },
+      'dependencies': [
+        'base',
+      ],
+      'export_dependent_settings': [
+        'base',
+      ],
+      'defines': [
+        'BASE_PREFS_IMPLEMENTATION',
+      ],
+      'sources': [
+        'prefs/default_pref_store.cc',
+        'prefs/default_pref_store.h',
+        'prefs/json_pref_store.cc',
+        'prefs/json_pref_store.h',
+        'prefs/overlay_user_pref_store.cc',
+        'prefs/overlay_user_pref_store.h',
+        'prefs/persistent_pref_store.h',
+        'prefs/pref_observer.h',
+        'prefs/pref_notifier.h',
+        'prefs/pref_store.cc',
+        'prefs/pref_store.h',
+        'prefs/pref_value_map.cc',
+        'prefs/pref_value_map.h',
+        'prefs/public/pref_change_registrar.cc',
+        'prefs/public/pref_change_registrar.h',
+        'prefs/public/pref_member.cc',
+        'prefs/public/pref_member.h',
+        'prefs/public/pref_service_base.h',
+        'prefs/value_map_pref_store.cc',
+        'prefs/value_map_pref_store.h',
+      ],
+      'conditions': [
+        ['OS == "starboard"', {
+          'sources!': [
+            # Uses ImportantFileWriter, which is not supported by Starboard.
+            'prefs/json_pref_store.cc',
+            'prefs/json_pref_store.h',
+          ],
+        }],  # OS=="starboard"
+      ],
+    },
+    {
+      # This is the subset of files from base that should not be used with a
+      # dynamic library. Note that this library cannot depend on base because
+      # base depends on base_static.
+      'target_name': 'base_static',
+      'type': 'static_library',
+      'variables': {
+        'enable_wexit_time_destructors': 1,
+        'optimize': 'max',
+      },
+      'toolsets': ['host', 'target'],
+      'sources': [
+        'base_switches.cc',
+        'base_switches.h',
+        'win/pe_image.cc',
+        'win/pe_image.h',
+      ],
+      'include_dirs': [
+        '..',
+      ],
+      'conditions': [
+        ['OS == "lb_shell" or OS=="starboard"', {
+          'sources/': [
+            ['exclude', '^win/'],
+          ],
+        }],
+      ],
+    },
+    {
+      # TODO(rvargas): Remove this when gyp finally supports a clean model.
+      # See bug 36232.
+      'target_name': 'base_static_win64',
+      'type': 'static_library',
+      'sources': [
+        'base_switches.cc',
+        'base_switches.h',
+        'win/pe_image.cc',
+        'win/pe_image.h',
+      ],
+      'sources!': [
+        # base64.cc depends on modp_b64.
+        'base64.cc',
+      ],
+      'include_dirs': [
+        '..',
+      ],
+      'configurations': {
+        'Common_Base': {
+          'msvs_target_platform': 'x64',
+        },
+      },
+      'defines': [
+        'NACL_WIN64',
+      ],
+      # TODO(rvargas): Bug 78117. Remove this.
+      'msvs_disabled_warnings': [
+        4244,
+      ],
+    },
+    # Include this target for a main() function that simply instantiates
+    # and runs a base::TestSuite.
+    {
+      'target_name': 'run_all_unittests',
+      'type': 'static_library',
+      'dependencies': [
+        'test_support_base',
+      ],
+      'sources': [
+        'test/run_all_unittests.cc',
+      ],
+    },
+    {
+      'target_name': 'base_unittests',
+      'type': '<(gtest_target_type)',
+      'sources': [
+        # Tests.
+        'android/jni_android_unittest.cc',
+        'android/jni_array_unittest.cc',
+        'android/jni_string_unittest.cc',
+        'android/path_utils_unittest.cc',
+        'android/scoped_java_ref_unittest.cc',
+        'at_exit_unittest.cc',
+        'atomicops_unittest.cc',
+        'base64_unittest.cc',
+        'bind_helpers_unittest.cc',
+        'bind_unittest.cc',
+        'bind_unittest.nc',
+        'bits_unittest.cc',
+        'build_time_unittest.cc',
+        'callback_unittest.cc',
+        'callback_unittest.nc',
+        'cancelable_callback_unittest.cc',
+        'command_line_unittest.cc',
+        'containers/linked_list_unittest.cc',
+        'containers/mru_cache_unittest.cc',
+        'containers/small_map_unittest.cc',
+        'containers/stack_container_unittest.cc',
+        'cpu_unittest.cc',
+        'debug/leak_tracker_unittest.cc',
+        'debug/stack_trace_unittest.cc',
+        'debug/trace_event_unittest.cc',
+        'debug/trace_event_unittest.h',
+        'debug/trace_event_win_unittest.cc',
+        'environment_unittest.cc',
+        'file_path_unittest.cc',
+        'file_util_proxy_unittest.cc',
+        'file_util_unittest.cc',
+        'file_version_info_unittest.cc',
+        'files/dir_reader_posix_unittest.cc',
+        'files/important_file_writer_unittest.cc',
+        'files/scoped_temp_dir_unittest.cc',
+        'gmock_unittest.cc',
+        'guid_unittest.cc',
+        'hi_res_timer_manager_unittest.cc',
+        'id_map_unittest.cc',
+        'i18n/break_iterator_unittest.cc',
+        'i18n/char_iterator_unittest.cc',
+        'i18n/case_conversion_unittest.cc',
+        'i18n/file_util_icu_unittest.cc',
+        'i18n/icu_string_conversions_unittest.cc',
+        'i18n/number_formatting_unittest.cc',
+        'i18n/rtl_unittest.cc',
+        'i18n/string_search_unittest.cc',
+        'i18n/time_formatting_unittest.cc',
+        'ios/device_util_unittest.mm',
+        'json/json_parser_unittest.cc',
+        'json/json_reader_unittest.cc',
+        'json/json_value_converter_unittest.cc',
+        'json/json_value_serializer_unittest.cc',
+        'json/json_writer_unittest.cc',
+        'json/string_escape_unittest.cc',
+        'lazy_instance_unittest.cc',
+        'logging_unittest.cc',
+        'mac/bind_objc_block_unittest.mm',
+        'mac/foundation_util_unittest.mm',
+        'mac/libdispatch_task_runner_unittest.cc',
+        'mac/mac_util_unittest.mm',
+        'mac/objc_property_releaser_unittest.mm',
+        'mac/scoped_sending_event_unittest.mm',
+        'md5_unittest.cc',
+        'memory/aligned_memory_unittest.cc',
+        'memory/linked_ptr_unittest.cc',
+        'memory/ref_counted_memory_unittest.cc',
+        'memory/ref_counted_unittest.cc',
+        'memory/scoped_nsobject_unittest.mm',
+        'memory/scoped_ptr_unittest.cc',
+        'memory/scoped_ptr_unittest.nc',
+        'memory/scoped_vector_unittest.cc',
+        'memory/singleton_unittest.cc',
+        'memory/weak_ptr_unittest.cc',
+        'memory/weak_ptr_unittest.nc',
+        'message_loop_proxy_impl_unittest.cc',
+        'message_loop_proxy_unittest.cc',
+        'message_loop_unittest.cc',
+        'message_pump_glib_unittest.cc',
+        'message_pump_io_ios_unittest.cc',
+        'message_pump_libevent_unittest.cc',
+        'metrics/sample_map_unittest.cc',
+        'metrics/sample_vector_unittest.cc',
+        'metrics/bucket_ranges_unittest.cc',
+        'metrics/field_trial_unittest.cc',
+        'metrics/histogram_unittest.cc',
+        'metrics/sparse_histogram_unittest.cc',
+        'metrics/stats_table_unittest.cc',
+        'metrics/statistics_recorder_unittest.cc',
+        'object_tracker.h',
+        'observer_list_unittest.cc',
+        'os_compat_android_unittest.cc',
+        'path_service_unittest.cc',
+        'pickle_unittest.cc',
+        'platform_file_unittest.cc',
+        'posix/file_descriptor_shuffle_unittest.cc',
+        'pr_time_unittest.cc',
+        'process_util_unittest.cc',
+        'process_util_unittest_ios.cc',
+        'process_util_unittest_mac.h',
+        'process_util_unittest_mac.mm',
+        'profiler/tracked_time_unittest.cc',
+        'rand_util_unittest.cc',
+        'scoped_native_library_unittest.cc',
+        'scoped_observer.h',
+        'sha1_unittest.cc',
+        'shared_memory_unittest.cc',
+        'stl_util_unittest.cc',
+        'string16_unittest.cc',
+        'string_number_conversions_unittest.cc',
+        'string_piece_unittest.cc',
+        'string_split_unittest.cc',
+        'string_tokenizer_unittest.cc',
+        'string_util_unittest.cc',
+        'stringize_macros_unittest.cc',
+        'stringprintf_unittest.cc',
+        'synchronization/cancellation_flag_unittest.cc',
+        'synchronization/condition_variable_unittest.cc',
+        'synchronization/lock_unittest.cc',
+        'synchronization/waitable_event_unittest.cc',
+        'synchronization/waitable_event_watcher_unittest.cc',
+        'sys_info_unittest.cc',
+        'sys_string_conversions_mac_unittest.mm',
+        'sys_string_conversions_unittest.cc',
+        'system_monitor/system_monitor_unittest.cc',
+        'task_runner_util_unittest.cc',
+        'template_util_unittest.cc',
+        'test/sequenced_worker_pool_owner.cc',
+        'test/sequenced_worker_pool_owner.h',
+        'test/trace_event_analyzer_unittest.cc',
+        'test/time_helpers.cc',
+        'test/time_helpers.h',
+        'threading/non_thread_safe_unittest.cc',
+        'threading/platform_thread_unittest.cc',
+        'threading/sequenced_worker_pool_unittest.cc',
+        'threading/simple_thread_unittest.cc',
+        'threading/thread_checker_unittest.cc',
+        'threading/thread_collision_warner_unittest.cc',
+        'threading/thread_local_storage_unittest.cc',
+        'threading/thread_local_unittest.cc',
+        'threading/thread_unittest.cc',
+        'threading/watchdog_unittest.cc',
+        'threading/worker_pool_posix_unittest.cc',
+        'threading/worker_pool_unittest.cc',
+        'time_unittest.cc',
+        'time_win_unittest.cc',
+        'timer_unittest.cc',
+        'tools_sanity_unittest.cc',
+        'tracked_objects_unittest.cc',
+        'tuple_unittest.cc',
+        'utf_offset_string_conversions_unittest.cc',
+        'utf_string_conversions_unittest.cc',
+        'values_unittest.cc',
+        'version_unittest.cc',
+        'vlog_unittest.cc',
+        'win/dllmain.cc',
+        'win/enum_variant_unittest.cc',
+        'win/event_trace_consumer_unittest.cc',
+        'win/event_trace_controller_unittest.cc',
+        'win/event_trace_provider_unittest.cc',
+        'win/i18n_unittest.cc',
+        'win/iunknown_impl_unittest.cc',
+        'win/object_watcher_unittest.cc',
+        'win/pe_image_unittest.cc',
+        'win/registry_unittest.cc',
+        'win/sampling_profiler_unittest.cc',
+        'win/scoped_bstr_unittest.cc',
+        'win/scoped_comptr_unittest.cc',
+        'win/scoped_process_information_unittest.cc',
+        'win/shortcut_unittest.cc',
+        'win/startup_information_unittest.cc',
+        'win/scoped_variant_unittest.cc',
+        'win/win_util_unittest.cc',
+        'win/wrapped_window_proc_unittest.cc',
+      ],
+      'dependencies': [
+        'base',
+        'base_i18n',
+        'base_static',
+        'run_all_unittests',
+        'test_support_base',
+        'third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../testing/gmock.gyp:gmock',
+        '../testing/gtest.gyp:gtest',
+        '../third_party/icu/icu.gyp:icui18n',
+        '../third_party/icu/icu.gyp:icuuc',
+      ],
+      'includes': ['../build/nocompile.gypi'],
+      'variables': {
+         # TODO(ajwong): Is there a way to autodetect this?
+        'module_dir': 'base'
+      },
+      'conditions': [
+        ['OS == "android"', {
+          'dependencies': [
+            'android/jni_generator/jni_generator.gyp:jni_generator_tests',
+          ],
+          'conditions': [
+            ['gtest_target_type == "shared_library"', {
+              'dependencies': [
+                '../testing/android/native_test.gyp:native_test_native_code',
+              ],
+            }],
+          ],
+          'sources!': [
+            # Broken on Android, and already disabled there.
+            'debug/stack_trace_unittest.cc',
+          ],
+        }],
+        ['OS == "ios"', {
+          'sources/': [
+            # Only test the iOS-meaningful portion of process_utils.
+            ['exclude', '^process_util_unittest'],
+            ['include', '^process_util_unittest_ios\\.cc$'],
+            # Requires spawning processes.
+            ['exclude', '^metrics/stats_table_unittest\\.cc$'],
+            # iOS does not use message_pump_libevent.
+            ['exclude', '^message_pump_libevent_unittest\\.cc$'],
+          ],
+          'conditions': [
+            ['coverage != 0', {
+              'sources!': [
+                # These sources can't be built with coverage due to a toolchain
+                # bug: http://openradar.appspot.com/radar?id=1499403
+                'json/json_reader_unittest.cc',
+                'string_piece_unittest.cc',
+
+                # These tests crash when run with coverage turned on due to an
+                # issue with llvm_gcda_increment_indirect_counter:
+                # http://crbug.com/156058
+                'debug/trace_event_unittest.cc',
+                'debug/trace_event_unittest.h',
+                'logging_unittest.cc',
+                'string_util_unittest.cc',
+                'test/trace_event_analyzer_unittest.cc',
+                'utf_offset_string_conversions_unittest.cc',
+              ],
+            }],
+          ],
+          'actions': [
+            {
+              'action_name': 'copy_test_data',
+              'variables': {
+                'test_data_files': [
+                  'data/json/bom_feff.json',
+                  'data/file_util_unittest',
+                ],
+                'test_data_prefix': 'base',
+              },
+              'includes': [ '../build/copy_test_data_ios.gypi' ],
+            },
+          ],
+        }],
+        ['cobalt==1', {
+          'actions': [
+            {
+              'action_name': 'copy_test_data',
+              'variables': {
+                'input_files': [
+                  'data/json',
+                  'data/file_util_unittest',
+                ],
+                'output_dir': 'base/data',
+              },
+              'includes': [ '../cobalt/build/copy_test_data.gypi' ],
+            },
+          ],
+        }],
+        ['use_glib==1', {
+          'sources!': [
+            'file_version_info_unittest.cc',
+          ],
+          'conditions': [
+            [ 'linux_use_tcmalloc==1', {
+                'dependencies': [
+                  'allocator/allocator.gyp:allocator',
+                ],
+              },
+            ],
+            [ 'toolkit_uses_gtk==1', {
+              'sources': [
+                'nix/xdg_util_unittest.cc',
+              ],
+              'dependencies': [
+                '../build/linux/system.gyp:gtk',
+              ]
+            }],
+          ],
+          'dependencies': [
+            '../build/linux/system.gyp:glib',
+            '../build/linux/system.gyp:ssl',
+            '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+          ],
+        }, {  # use_glib!=1
+          'sources!': [
+            'message_pump_glib_unittest.cc',
+          ]
+        }],
+        # This is needed to trigger the dll copy step on windows.
+        # TODO(mark): This should not be necessary.
+        ['OS == "win"', {
+          'dependencies': [
+            '../third_party/icu/icu.gyp:icudata',
+          ],
+          'sources!': [
+            'file_descriptor_shuffle_unittest.cc',
+            'files/dir_reader_posix_unittest.cc',
+            'threading/worker_pool_posix_unittest.cc',
+            'message_pump_libevent_unittest.cc',
+          ],
+        }, {  # OS != "win"
+          'dependencies': [
+            '../third_party/libevent/libevent.gyp:libevent'
+          ],
+          'sources/': [
+            ['exclude', '^win/'],
+          ],
+          'sources!': [
+            'debug/trace_event_win_unittest.cc',
+            'time_win_unittest.cc',
+            'win/win_util_unittest.cc',
+          ],
+        }],
+        ['OS == "lb_shell" or OS == "starboard"', {
+          'sources!': [
+            'environment_unittest.cc',
+            'files/important_file_writer_unittest.cc',
+            # We don't use field trials (an experiments framework) in Cobalt,
+            # and these tests depend on the current date being set correctly,
+            # so do not run them.
+            'metrics/field_trial_unittest.cc',
+            'metrics/stats_table_unittest.cc',
+            'process_util_unittest.cc',
+            'scoped_native_library_unittest.cc',
+            'shared_memory_unittest.cc',
+            'synchronization/waitable_event_watcher_unittest.cc',
+          ],
+          'sources': [
+            'circular_buffer_shell_unittest.cc',
+            'optional_unittest.cc',
+            'state_machine_shell_unittest.cc',
+          ],
+          'conditions': [
+            ['target_arch != "android" or OS == "starboard"', {
+              'dependencies!': [
+                '../third_party/libevent/libevent.gyp:libevent'
+              ],
+              'sources!': [
+                'message_pump_libevent_unittest.cc',
+              ],
+            }],
+          ],
+        }],
+      ],  # conditions
+      'target_conditions': [
+        ['OS == "ios"', {
+          'sources/': [
+            # Pull in specific Mac files for iOS (which have been filtered out
+            # by file name rules).
+            ['include', '^mac/objc_property_releaser_unittest\\.mm$'],
+            ['include', '^mac/bind_objc_block_unittest\\.mm$'],
+            ['include', '^sys_string_conversions_mac_unittest\\.mm$'],
+          ],
+        }],
+      ],  # target_conditions
+      'msvs_disabled_warnings': [
+        4800,  # forcing value to bool 'true' or 'false' (performance warning)
+      ],
+    },
+    {
+      'target_name': 'test_support_base',
+      'type': 'static_library',
+      'dependencies': [
+        'base',
+        'base_static',
+        'base_i18n',
+        '../testing/gmock.gyp:gmock',
+        '../testing/gtest.gyp:gtest',
+      ],
+      'export_dependent_settings': [
+        'base',
+      ],
+      'conditions': [
+        ['cobalt==1', {
+          'dependencies': [
+            # Platform delegate is used to perform system specific
+            # initialization logic. This is a temporary solution and the code
+            # should eventually move into the chromium/base code.
+            '<(DEPTH)/cobalt/deprecated/deprecated.gyp:platform_delegate',
+          ],
+        }],
+        ['toolkit_uses_gtk==1', {
+          'dependencies': [
+            # test_suite initializes GTK.
+            '../build/linux/system.gyp:gtk',
+          ],
+        }],
+        ['os_posix==0', {
+          'sources!': [
+            'test/scoped_locale.cc',
+            'test/scoped_locale.h',
+          ],
+        }],
+        ['os_bsd==1', {
+          'sources!': [
+            'test/test_file_util_linux.cc',
+          ],
+        }],
+        ['OS=="win"', {
+          'direct_dependent_settings': {
+            'msvs_settings': {
+              'VCLinkerTool': {
+                'DelayLoadDLLs': [
+                  'propsys.dll',
+                ],
+              },
+            },
+          },
+        }],
+      ],
+      'sources': [
+        'perftimer.cc',
+        'test/main_hook.cc',
+        'test/main_hook.h',
+        'test/main_hook_ios.mm',
+        'test/mock_chrome_application_mac.h',
+        'test/mock_chrome_application_mac.mm',
+        'test/mock_devices_changed_observer.cc',
+        'test/mock_devices_changed_observer.h',
+        'test/mock_time_provider.cc',
+        'test/mock_time_provider.h',
+        'test/multiprocess_test.cc',
+        'test/multiprocess_test.h',
+        'test/multiprocess_test_android.cc',
+        'test/perf_test_suite.cc',
+        'test/perf_test_suite.h',
+        'test/scoped_locale.cc',
+        'test/scoped_locale.h',
+        'test/scoped_path_override.cc',
+        'test/scoped_path_override.h',
+        'test/sequenced_task_runner_test_template.cc',
+        'test/sequenced_task_runner_test_template.h',
+        'test/task_runner_test_template.cc',
+        'test/task_runner_test_template.h',
+        'test/test_file_util.h',
+        'test/test_file_util_linux.cc',
+        'test/test_file_util_mac.cc',
+        'test/test_file_util_posix.cc',
+        'test/test_file_util_win.cc',
+        'test/test_listener_ios.h',
+        'test/test_listener_ios.mm',
+        'test/test_reg_util_win.cc',
+        'test/test_reg_util_win.h',
+        'test/test_shortcut_win.cc',
+        'test/test_shortcut_win.h',
+        'test/test_suite.cc',
+        'test/test_suite.h',
+        'test/test_support_android.cc',
+        'test/test_support_android.h',
+        'test/test_support_ios.h',
+        'test/test_support_ios.mm',
+        'test/test_switches.cc',
+        'test/test_switches.h',
+        'test/test_timeouts.cc',
+        'test/test_timeouts.h',
+        'test/thread_test_helper.cc',
+        'test/thread_test_helper.h',
+        'test/trace_event_analyzer.cc',
+        'test/trace_event_analyzer.h',
+        'test/values_test_util.cc',
+        'test/values_test_util.h',
+      ],
+      'target_conditions': [
+        ['OS == "ios"', {
+          'sources/': [
+            # Pull in specific Mac files for iOS (which have been filtered out
+            # by file name rules).
+            ['include', '^test/test_file_util_mac\\.cc$'],
+          ],
+        }],
+        ['OS == "lb_shell" or OS=="starboard"', {
+          'sources/': [
+            ['exclude', 'test/multiprocess_test'],
+          ],
+          'sources!': [
+            'perftimer.cc',
+          ],
+          'sources': [
+            'perftimer_starboard.cc',
+          ],
+        }],
+      ],  # target_conditions
+    },
+    {
+      'target_name': 'test_support_perf',
+      'type': 'static_library',
+      'dependencies': [
+        'base',
+        '../testing/gtest.gyp:gtest',
+      ],
+      'sources': [
+        'perftimer.cc',
+        'test/run_all_perftests.cc',
+      ],
+      'direct_dependent_settings': {
+        'defines': [
+          'PERF_TEST',
+        ],
+      },
+      'conditions': [
+        ['toolkit_uses_gtk==1', {
+          'dependencies': [
+            # Needed to handle the #include chain:
+            #   base/test/perf_test_suite.h
+            #   base/test/test_suite.h
+            #   gtk/gtk.h
+            '../build/linux/system.gyp:gtk',
+          ],
+        }],
+        ['OS=="starboard"', {
+          'sources!': [
+            'perftimer.cc',
+          ],
+          'sources': [
+            'perftimer_starboard.cc',
+          ],
+        }],
+      ],
+    },
+  ],
+  'conditions': [
+    ['OS!="ios"', {
+      'targets': [
+        {
+          'target_name': 'check_example',
+          'type': 'executable',
+          'sources': [
+            'check_example.cc',
+          ],
+          'dependencies': [
+            'base',
+          ],
+        },
+      ],
+    }],
+    ['OS == "win"', {
+      'targets': [
+        {
+          'target_name': 'base_nacl_win64',
+          'type': '<(component)',
+          'variables': {
+            'base_target': 1,
+          },
+          'dependencies': [
+            'base_static_win64',
+            'allocator/allocator.gyp:allocator_extension_thunks_win64',
+            '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': [
+              '..',
+            ],
+          },
+          'defines': [
+            '<@(nacl_win64_defines)',
+          ],
+          'sources!': [
+            # base64.cc depends on modp_b64.
+            'base64.cc',
+          ],
+          'configurations': {
+            'Common_Base': {
+              'msvs_target_platform': 'x64',
+            },
+          },
+          'conditions': [
+            ['component == "shared_library"', {
+              'sources!': [
+                'debug/debug_on_start_win.cc',
+              ],
+            }],
+          ],
+        },
+        {
+          'target_name': 'base_i18n_nacl_win64',
+          'type': '<(component)',
+          # 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': [
+              '..',
+            ],
+          },
+          'defines': [
+            '<@(nacl_win64_defines)',
+            'BASE_I18N_IMPLEMENTATION',
+          ],
+          'include_dirs': [
+            '..',
+          ],
+          'sources': [
+            'i18n/icu_util_nacl_win64.cc',
+          ],
+          'configurations': {
+            'Common_Base': {
+              'msvs_target_platform': 'x64',
+            },
+          },
+        },
+      ],
+    }],
+    ['os_posix==1 and OS!="mac" and OS!="ios" and (OS!="lb_shell" or target_arch in ("android", "linux"))', {
+      'targets': [
+        {
+          'target_name': 'symbolize',
+          'type': 'static_library',
+          'toolsets': ['host', 'target'],
+          'variables': {
+            'chromium_code': 0,
+          },
+          'conditions': [
+            ['OS == "solaris"', {
+              'include_dirs': [
+                '/usr/gnu/include',
+                '/usr/gnu/include/libelf',
+              ],
+            },],
+          ],
+          'cflags': [
+            '-Wno-sign-compare',
+          ],
+          'cflags!': [
+            '-Wextra',
+          ],
+          'sources': [
+            'third_party/symbolize/config.h',
+            'third_party/symbolize/demangle.cc',
+            'third_party/symbolize/demangle.h',
+            'third_party/symbolize/glog/logging.h',
+            'third_party/symbolize/glog/raw_logging.h',
+            'third_party/symbolize/symbolize.cc',
+            'third_party/symbolize/symbolize.h',
+            'third_party/symbolize/utilities.h',
+          ],
+          'include_dirs': [
+            '..',
+          ],
+        },
+        {
+          'target_name': 'xdg_mime',
+          'type': 'static_library',
+          'toolsets': ['host', 'target'],
+          'variables': {
+            'chromium_code': 0,
+          },
+          'cflags!': [
+            '-Wextra',
+          ],
+          'sources': [
+            'third_party/xdg_mime/xdgmime.c',
+            'third_party/xdg_mime/xdgmime.h',
+            'third_party/xdg_mime/xdgmimealias.c',
+            'third_party/xdg_mime/xdgmimealias.h',
+            'third_party/xdg_mime/xdgmimecache.c',
+            'third_party/xdg_mime/xdgmimecache.h',
+            'third_party/xdg_mime/xdgmimeglob.c',
+            'third_party/xdg_mime/xdgmimeglob.h',
+            'third_party/xdg_mime/xdgmimeicon.c',
+            'third_party/xdg_mime/xdgmimeicon.h',
+            'third_party/xdg_mime/xdgmimeint.c',
+            'third_party/xdg_mime/xdgmimeint.h',
+            'third_party/xdg_mime/xdgmimemagic.c',
+            'third_party/xdg_mime/xdgmimemagic.h',
+            'third_party/xdg_mime/xdgmimeparent.c',
+            'third_party/xdg_mime/xdgmimeparent.h',
+          ],
+        },
+      ],
+    }],
+    ['OS == "android" or ((OS == "lb_shell" or OS == "starboard") and target_arch == "android")', {
+      'targets': [
+        {
+          'target_name': 'base_jni_headers',
+          'type': 'none',
+          'sources': [
+            'android/java/src/org/chromium/base/BuildInfo.java',
+            'android/java/src/org/chromium/base/CpuFeatures.java',
+            'android/java/src/org/chromium/base/LocaleUtils.java',
+            'android/java/src/org/chromium/base/PathService.java',
+            'android/java/src/org/chromium/base/PathUtils.java',
+            'android/java/src/org/chromium/base/SystemMessageHandler.java',
+            'android/java/src/org/chromium/base/SystemMonitor.java',
+          ],
+          'variables': {
+            'jni_gen_dir': 'base',
+          },
+          'includes': [ '../build/jni_generator.gypi' ],
+        },
+        {
+          'target_name': 'base_java',
+          'type': 'none',
+          'variables': {
+            'package_name': 'base',
+            'java_in_dir': '../base/android/java',
+          },
+          'includes': [ '../build/java.gypi' ],
+        },
+        {
+          'target_name': 'base_java_test_support',
+          'type': 'none',
+          'dependencies': [
+            'base_java',
+          ],
+          'variables': {
+            'package_name': 'base_javatests',
+            'java_in_dir': '../base/test/android/javatests',
+          },
+          'includes': [ '../build/java.gypi' ],
+        },
+      ],
+    }],
+    ['OS == "win"', {
+      'targets': [
+        {
+          'target_name': 'debug_message',
+          'type': 'executable',
+          'sources': [
+            'debug_message.cc',
+          ],
+          'msvs_settings': {
+            'VCLinkerTool': {
+              'SubSystem': '2',         # Set /SUBSYSTEM:WINDOWS
+            },
+          },
+        },
+      ],
+    }],
+    ['cobalt==1', {
+      'targets': [
+        {
+          'target_name': 'base_unittests_deploy',
+          'type': 'none',
+          'dependencies': [
+            'base_unittests',
+          ],
+          'variables': {
+            'executable_name': 'base_unittests',
+          },
+          'includes': [ '../cobalt/build/deploy.gypi' ],
+        },
+      ],
+    }],
+    # Special target to wrap a gtest_target_type == shared_library
+    # base_unittests into an android apk for execution.
+    # TODO(jrg): lib.target comes from _InstallableTargetInstallPath()
+    # in the gyp make generator.  What is the correct way to extract
+    # this path from gyp and into 'raw' for input to antfiles?
+    # Hard-coding in the gypfile seems a poor choice.
+    ['(OS == "android" and gtest_target_type == "shared_library") or ((OS == "lb_shell" or OS == "starboard") and target_arch == "android")', {
+      'targets': [
+        {
+          'target_name': 'base_unittests_apk',
+          'type': 'none',
+          'dependencies': [
+            'base_java',
+            'base_unittests',
+          ],
+          'variables': {
+            'test_suite_name': 'base_unittests',
+            'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)base_unittests<(SHARED_LIB_SUFFIX)',
+          },
+          'includes': [ '../build/apk_test.gypi' ],
+        },
+      ],
+    }],
+    ['test_isolation_mode != "noop"', {
+      'targets': [
+        {
+          'target_name': 'base_unittests_run',
+          'type': 'none',
+          'dependencies': [
+            'base_unittests',
+          ],
+          'includes': [
+            '../build/isolate.gypi',
+            'base_unittests.isolate',
+          ],
+          'sources': [
+            'base_unittests.isolate',
+          ],
+        },
+      ],
+    }],
+  ],
+}
diff --git a/src/base/base.gypi b/src/base/base.gypi
new file mode 100644
index 0000000..fde1a96
--- /dev/null
+++ b/src/base/base.gypi
@@ -0,0 +1,858 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'target_defaults': {
+    'variables': {
+      'base_target': 0,
+    },
+    'target_conditions': [
+      # This part is shared between the targets defined below.
+      ['base_target==1', {
+        'sources': [
+          '../build/build_config.h',
+          'third_party/dmg_fp/dmg_fp.h',
+          'third_party/dmg_fp/g_fmt.cc',
+          'third_party/dmg_fp/dtoa_wrapper.cc',
+          'third_party/icu/icu_utf.cc',
+          'third_party/icu/icu_utf.h',
+          'third_party/nspr/prtime.cc',
+          'third_party/nspr/prtime.h',
+          'third_party/nspr/prcpucfg_linux.h',
+          'third_party/xdg_mime/xdgmime.h',
+          'allocator/allocator_extension.cc',
+          'allocator/allocator_extension.h',
+          'allocator/type_profiler_control.cc',
+          'allocator/type_profiler_control.h',
+          'android/base_jni_registrar.cc',
+          'android/base_jni_registrar.h',
+          'android/build_info.cc',
+          'android/build_info.h',
+          'android/cpu_features.cc',
+          'android/scoped_java_ref.cc',
+          'android/scoped_java_ref.h',
+          'android/jni_android.cc',
+          'android/jni_android.h',
+          'android/jni_array.cc',
+          'android/jni_array.h',
+          'android/jni_helper.cc',
+          'android/jni_helper.h',
+          'android/jni_registrar.cc',
+          'android/jni_registrar.h',
+          'android/jni_string.cc',
+          'android/jni_string.h',
+          'android/locale_utils.cc',
+          'android/locale_utils.h',
+          'android/path_service_android.cc',
+          'android/path_service_android.h',
+          'android/path_utils.cc',
+          'android/path_utils.h',
+          'at_exit.cc',
+          'at_exit.h',
+          'atomic_ref_count.h',
+          'atomic_sequence_num.h',
+          'atomicops.h',
+          'atomicops_internals_gcc.h',
+          'atomicops_internals_mac.h',
+          'atomicops_internals_tsan.h',
+          'atomicops_internals_x86_gcc.cc',
+          'atomicops_internals_x86_gcc.h',
+          'atomicops_internals_x86_msvc.h',
+          'base_export.h',
+          'base_paths.cc',
+          'base_paths.h',
+          'base_paths_android.cc',
+          'base_paths_android.h',
+          'base_paths_mac.h',
+          'base_paths_mac.mm',
+          'base_paths_posix.cc',
+          'base_paths_posix.h',
+          'base_paths_win.cc',
+          'base_paths_win.h',
+          'base_switches.h',
+          'base64.cc',
+          'base64.h',
+          'basictypes.h',
+          'bind.h',
+          'bind_helpers.cc',
+          'bind_helpers.h',
+          'bind_internal.h',
+          'bind_internal_functor.h',
+          'bind_internal_win.h',
+          'bits.h',
+          'build_time.cc',
+          'build_time.h',
+          'callback.h',
+          'callback_helpers.h',
+          'callback_internal.cc',
+          'callback_internal.h',
+          'cancelable_callback.h',
+          'chromeos/chromeos_version.cc',
+          'chromeos/chromeos_version.h',
+          'command_line.cc',
+          'command_line.h',
+          'compiler_specific.h',
+          'containers/linked_hash_map.h',
+          'containers/linked_list.h',
+          'containers/mru_cache.h',
+          'containers/small_map.h',
+          'containers/stack_container.h',
+          'cpu.cc',
+          'cpu.h',
+          'critical_closure.h',
+          'critical_closure_ios.mm',
+          'debug/alias.cc',
+          'debug/alias.h',
+          'debug/debug_on_start_win.cc',
+          'debug/debug_on_start_win.h',
+          'debug/debugger.cc',
+          'debug/debugger.h',
+          'debug/debugger_posix.cc',
+          'debug/debugger_win.cc',
+          # This file depends on files from the 'allocator' target,
+          # but this target does not depend on 'allocator' (see
+          # allocator.gyp for details).
+          'debug/leak_annotations.h',
+          'debug/leak_tracker.h',
+          'debug/profiler.cc',
+          'debug/profiler.h',
+          'debug/stack_trace.cc',
+          'debug/stack_trace.h',
+          'debug/stack_trace_android.cc',
+          'debug/stack_trace_ios.mm',
+          'debug/stack_trace_posix.cc',
+          'debug/stack_trace_win.cc',
+          'debug/trace_event.cc',
+          'debug/trace_event.h',
+          'debug/trace_event_android.cc',
+          'debug/trace_event_impl.cc',
+          'debug/trace_event_impl.h',
+          'debug/trace_event_win.cc',
+          'environment.cc',
+          'environment.h',
+          'file_descriptor_posix.h',
+          'file_path.cc',
+          'file_path.h',
+          'file_util.cc',
+          'file_util.h',
+          'file_util_android.cc',
+          'file_util_linux.cc',
+          'file_util_mac.mm',
+          'file_util_posix.cc',
+          'file_util_win.cc',
+          'file_util_proxy.cc',
+          'file_util_proxy.h',
+          'file_version_info.h',
+          'file_version_info_mac.h',
+          'file_version_info_mac.mm',
+          'file_version_info_win.cc',
+          'file_version_info_win.h',
+          'files/dir_reader_fallback.h',
+          'files/dir_reader_dirent.h',
+          'files/dir_reader_linux.h',
+          'files/dir_reader_posix.h',
+          'files/file_path_watcher.cc',
+          'files/file_path_watcher.h',
+          'files/file_path_watcher_kqueue.cc',
+          'files/file_path_watcher_linux.cc',
+          'files/file_path_watcher_stub.cc',
+          'files/file_path_watcher_win.cc',
+          'files/important_file_writer.h',
+          'files/important_file_writer.cc',
+          'files/scoped_temp_dir.cc',
+          'files/scoped_temp_dir.h',
+          'float_util.h',
+          'format_macros.h',
+          'gtest_prod_util.h',
+          'guid.cc',
+          'guid.h',
+          'guid_posix.cc',
+          'guid_win.cc',
+          'hash.cc',
+          'hash.h',
+          'hash_tables.h',
+          'hi_res_timer_manager_posix.cc',
+          'hi_res_timer_manager_win.cc',
+          'hi_res_timer_manager.h',
+          'id_map.h',
+          'ios/device_util.h',
+          'ios/device_util.mm',
+          'ios/ios_util.h',
+          'ios/ios_util.mm',
+          'ios/scoped_critical_action.h',
+          'ios/scoped_critical_action.mm',
+          'json/json_file_value_serializer.cc',
+          'json/json_file_value_serializer.h',
+          'json/json_parser.cc',
+          'json/json_parser.h',
+          'json/json_reader.cc',
+          'json/json_reader.h',
+          'json/json_string_value_serializer.cc',
+          'json/json_string_value_serializer.h',
+          'json/json_value_converter.h',
+          'json/json_writer.cc',
+          'json/json_writer.h',
+          'json/string_escape.cc',
+          'json/string_escape.h',
+          'lazy_instance.cc',
+          'lazy_instance.h',
+          'location.cc',
+          'location.h',
+          'logging.cc',
+          'logging.h',
+          'logging_win.cc',
+          'logging_win.h',
+          'mac/authorization_util.h',
+          'mac/authorization_util.mm',
+          'mac/bind_objc_block.h',
+          'mac/bind_objc_block.mm',
+          'mac/bundle_locations.h',
+          'mac/bundle_locations.mm',
+          'mac/cocoa_protocols.h',
+          'mac/crash_logging.h',
+          'mac/crash_logging.mm',
+          'mac/foundation_util.h',
+          'mac/foundation_util.mm',
+          'mac/launchd.cc',
+          'mac/launchd.h',
+          'mac/libdispatch_task_runner.cc',
+          'mac/libdispatch_task_runner.h',
+          'mac/mac_logging.h',
+          'mac/mac_logging.cc',
+          'mac/mac_util.h',
+          'mac/mac_util.mm',
+          'mac/objc_property_releaser.h',
+          'mac/objc_property_releaser.mm',
+          'mac/os_crash_dumps.cc',
+          'mac/os_crash_dumps.h',
+          'mac/scoped_aedesc.h',
+          'mac/scoped_authorizationref.h',
+          'mac/scoped_cftyperef.h',
+          'mac/scoped_ioobject.h',
+          'mac/scoped_launch_data.h',
+          'mac/scoped_mach_port.cc',
+          'mac/scoped_mach_port.h',
+          'mac/scoped_nsautorelease_pool.h',
+          'mac/scoped_nsautorelease_pool.mm',
+          'mac/scoped_nsexception_enabler.h',
+          'mac/scoped_nsexception_enabler.mm',
+          'mac/scoped_sending_event.h',
+          'mac/scoped_sending_event.mm',
+          'mach_ipc_mac.h',
+          'mach_ipc_mac.mm',
+          'memory/aligned_memory.cc',
+          'memory/aligned_memory.h',
+          'memory/linked_ptr.h',
+          'memory/manual_constructor.h',
+          'memory/raw_scoped_refptr_mismatch_checker.h',
+          'memory/ref_counted.cc',
+          'memory/ref_counted.h',
+          'memory/ref_counted_memory.cc',
+          'memory/ref_counted_memory.h',
+          'memory/scoped_handle.h',
+          'memory/scoped_nsobject.h',
+          'memory/scoped_open_process.h',
+          'memory/scoped_policy.h',
+          'memory/scoped_ptr.h',
+          'memory/scoped_vector.h',
+          'memory/singleton.cc',
+          'memory/singleton.h',
+          'memory/weak_ptr.cc',
+          'memory/weak_ptr.h',
+          'message_loop.cc',
+          'message_loop.h',
+          'message_loop_proxy.cc',
+          'message_loop_proxy.h',
+          'message_loop_proxy_impl.cc',
+          'message_loop_proxy_impl.h',
+          'message_pump.cc',
+          'message_pump.h',
+          'message_pump_android.cc',
+          'message_pump_android.h',
+          'message_pump_default.cc',
+          'message_pump_default.h',
+          'message_pump_win.cc',
+          'message_pump_win.h',
+          'metrics/sample_map.cc',
+          'metrics/sample_map.h',
+          'metrics/sample_vector.cc',
+          'metrics/sample_vector.h',
+          'metrics/bucket_ranges.cc',
+          'metrics/bucket_ranges.h',
+          'metrics/histogram.cc',
+          'metrics/histogram.h',
+          'metrics/histogram_base.cc',
+          'metrics/histogram_base.h',
+          'metrics/histogram_flattener.h',
+          'metrics/histogram_samples.cc',
+          'metrics/histogram_samples.h',
+          'metrics/histogram_snapshot_manager.cc',
+          'metrics/histogram_snapshot_manager.h',
+          'metrics/sparse_histogram.cc',
+          'metrics/sparse_histogram.h',
+          'metrics/statistics_recorder.cc',
+          'metrics/statistics_recorder.h',
+          'metrics/stats_counters.cc',
+          'metrics/stats_counters.h',
+          'metrics/stats_table.cc',
+          'metrics/stats_table.h',
+          'move.h',
+          'native_library.h',
+          'native_library_mac.mm',
+          'native_library_posix.cc',
+          'native_library_win.cc',
+          'observer_list.h',
+          'observer_list_threadsafe.h',
+          'os_compat_android.cc',
+          'os_compat_android.h',
+          'os_compat_nacl.cc',
+          'os_compat_nacl.h',
+          'path_service.cc',
+          'path_service.h',
+          'pending_task.cc',
+          'pending_task.h',
+          'pickle.cc',
+          'pickle.h',
+          'platform_file.cc',
+          'platform_file.h',
+          'platform_file_posix.cc',
+          'platform_file_win.cc',
+          'port.h',
+          'posix/eintr_wrapper.h',
+          'posix/global_descriptors.cc',
+          'posix/global_descriptors.h',
+          'posix/unix_domain_socket.cc',
+          'posix/unix_domain_socket.h',
+          'process.h',
+          'process_info.h',
+          'process_info_mac.cc',
+          'process_info_win.cc',
+          'process_linux.cc',
+          'process_posix.cc',
+          'process_util.cc',
+          'process_util.h',
+          'process_util_freebsd.cc',
+          'process_util_ios.mm',
+          'process_util_linux.cc',
+          'process_util_mac.mm',
+          'process_util_openbsd.cc',
+          'process_util_posix.cc',
+          'process_util_win.cc',
+          'process_win.cc',
+          'profiler/scoped_profile.cc',
+          'profiler/scoped_profile.h',
+          'profiler/alternate_timer.cc',
+          'profiler/alternate_timer.h',
+          'profiler/tracked_time.cc',
+          'profiler/tracked_time.h',
+          'rand_util.cc',
+          'rand_util.h',
+          'rand_util_nacl.cc',
+          'rand_util_posix.cc',
+          'rand_util_win.cc',
+          'run_loop.cc',
+          'run_loop.h',
+          'safe_strerror_posix.cc',
+          'safe_strerror_posix.h',
+          'scoped_native_library.cc',
+          'scoped_native_library.h',
+          'sequenced_task_runner.cc',
+          'sequenced_task_runner.h',
+          'sequenced_task_runner_helpers.h',
+          'sha1.h',
+          'sha1_portable.cc',
+          'sha1_win.cc',
+          'shared_memory.h',
+          'shared_memory_android.cc',
+          'shared_memory_nacl.cc',
+          'shared_memory_posix.cc',
+          'shared_memory_win.cc',
+          'single_thread_task_runner.h',
+          'stl_util.h',
+          'string_number_conversions.cc',
+          'string_number_conversions.h',
+          'string_piece.cc',
+          'string_piece.h',
+          'string_split.cc',
+          'string_split.h',
+          'string_tokenizer.h',
+          'string_util.cc',
+          'string_util.h',
+          'string_util_posix.h',
+          'string_util_win.h',
+          'string16.cc',
+          'string16.h',
+          'stringize_macros.h',
+          'stringprintf.cc',
+          'stringprintf.h',
+          'supports_user_data.cc',
+          'supports_user_data.h',
+          'synchronization/cancellation_flag.cc',
+          'synchronization/cancellation_flag.h',
+          'synchronization/condition_variable.h',
+          'synchronization/condition_variable_posix.cc',
+          'synchronization/condition_variable_win.cc',
+          'synchronization/lock.cc',
+          'synchronization/lock.h',
+          'synchronization/lock_impl.h',
+          'synchronization/lock_impl_posix.cc',
+          'synchronization/lock_impl_win.cc',
+          'synchronization/waitable_event.h',
+          'synchronization/waitable_event_posix.cc',
+          'synchronization/waitable_event_watcher.h',
+          'synchronization/waitable_event_watcher_posix.cc',
+          'synchronization/waitable_event_watcher_win.cc',
+          'synchronization/waitable_event_win.cc',
+          'system_monitor/system_monitor.cc',
+          'system_monitor/system_monitor.h',
+          'system_monitor/system_monitor_android.cc',
+          'system_monitor/system_monitor_android.h',
+          'system_monitor/system_monitor_ios.mm',
+          'system_monitor/system_monitor_mac.mm',
+          'system_monitor/system_monitor_posix.cc',
+          'system_monitor/system_monitor_win.cc',
+          'sys_byteorder.h',
+          'sys_info.cc',
+          'sys_info.h',
+          'sys_info_android.cc',
+          'sys_info_chromeos.cc',
+          'sys_info_freebsd.cc',
+          'sys_info_ios.mm',
+          'sys_info_linux.cc',
+          'sys_info_mac.cc',
+          'sys_info_openbsd.cc',
+          'sys_info_posix.cc',
+          'sys_info_win.cc',
+          'sys_string_conversions.h',
+          'sys_string_conversions_mac.mm',
+          'sys_string_conversions_posix.cc',
+          'sys_string_conversions_win.cc',
+          'task_runner.cc',
+          'task_runner.h',
+          'task_runner_util.h',
+          'template_util.h',
+          'thread_task_runner_handle.cc',
+          'thread_task_runner_handle.h',
+          'threading/non_thread_safe.h',
+          'threading/non_thread_safe_impl.cc',
+          'threading/non_thread_safe_impl.h',
+          'threading/platform_thread.h',
+          'threading/platform_thread_mac.mm',
+          'threading/platform_thread_posix.cc',
+          'threading/platform_thread_win.cc',
+          'threading/post_task_and_reply_impl.cc',
+          'threading/post_task_and_reply_impl.h',
+          'threading/sequenced_worker_pool.cc',
+          'threading/sequenced_worker_pool.h',
+          'threading/simple_thread.cc',
+          'threading/simple_thread.h',
+          'threading/thread.cc',
+          'threading/thread.h',
+          'threading/thread_checker.h',
+          'threading/thread_checker_impl.cc',
+          'threading/thread_checker_impl.h',
+          'threading/thread_collision_warner.cc',
+          'threading/thread_collision_warner.h',
+          'threading/thread_local.h',
+          'threading/thread_local_posix.cc',
+          'threading/thread_local_storage.h',
+          'threading/thread_local_storage_posix.cc',
+          'threading/thread_local_storage_win.cc',
+          'threading/thread_local_win.cc',
+          'threading/thread_restrictions.h',
+          'threading/thread_restrictions.cc',
+          'threading/watchdog.cc',
+          'threading/watchdog.h',
+          'threading/worker_pool.h',
+          'threading/worker_pool.cc',
+          'threading/worker_pool_posix.cc',
+          'threading/worker_pool_posix.h',
+          'threading/worker_pool_win.cc',
+          'time.cc',
+          'time.h',
+          'time_mac.cc',
+          'time_posix.cc',
+          'time_win.cc',
+          'timer.cc',
+          'timer.h',
+          'tracked_objects.cc',
+          'tracked_objects.h',
+          'tracking_info.cc',
+          'tracking_info.h',
+          'tuple.h',
+          'utf_offset_string_conversions.cc',
+          'utf_offset_string_conversions.h',
+          'utf_string_conversion_utils.cc',
+          'utf_string_conversion_utils.h',
+          'utf_string_conversions.cc',
+          'utf_string_conversions.h',
+          'values.cc',
+          'values.h',
+          'value_conversions.cc',
+          'value_conversions.h',
+          'version.cc',
+          'version.h',
+          'vlog.cc',
+          'vlog.h',
+          'nix/mime_util_xdg.cc',
+          'nix/mime_util_xdg.h',
+          'nix/xdg_util.cc',
+          'nix/xdg_util.h',
+          'win/enum_variant.h',
+          'win/enum_variant.cc',
+          'win/event_trace_consumer.h',
+          'win/event_trace_controller.cc',
+          'win/event_trace_controller.h',
+          'win/event_trace_provider.cc',
+          'win/event_trace_provider.h',
+          'win/i18n.cc',
+          'win/i18n.h',
+          'win/iat_patch_function.cc',
+          'win/iat_patch_function.h',
+          'win/iunknown_impl.h',
+          'win/iunknown_impl.cc',
+          'win/metro.cc',
+          'win/metro.h',
+          'win/object_watcher.cc',
+          'win/object_watcher.h',
+          'win/registry.cc',
+          'win/registry.h',
+          'win/resource_util.cc',
+          'win/resource_util.h',
+          'win/sampling_profiler.cc',
+          'win/sampling_profiler.h',
+          'win/scoped_bstr.cc',
+          'win/scoped_bstr.h',
+          'win/scoped_co_mem.h',
+          'win/scoped_com_initializer.h',
+          'win/scoped_comptr.h',
+          'win/scoped_gdi_object.h',
+          'win/scoped_handle.cc',
+          'win/scoped_handle.h',
+          'win/scoped_hdc.h',
+          'win/scoped_hglobal.h',
+          'win/scoped_process_information.cc',
+          'win/scoped_process_information.h',
+          'win/scoped_select_object.h',
+          'win/shortcut.cc',
+          'win/shortcut.h',
+          'win/startup_information.cc',
+          'win/startup_information.h',
+          'win/scoped_variant.cc',
+          'win/scoped_variant.h',
+          'win/text_services_message_filter.cc',
+          'win/text_services_message_filter.h',
+          'win/windows_version.cc',
+          'win/windows_version.h',
+          'win/win_util.cc',
+          'win/win_util.h',
+          'win/wrapped_window_proc.cc',
+          'win/wrapped_window_proc.h',
+        ],
+        'defines': [
+          'BASE_IMPLEMENTATION',
+        ],
+        'include_dirs': [
+          '..',
+        ],
+        'msvs_disabled_warnings': [
+          4018,
+        ],
+        'conditions': [
+          ['OS=="lb_shell"', {
+            'sources': [
+              'base_paths_shell.cc',
+              'circular_buffer_shell.h',
+              'circular_buffer_shell.cc',
+              'message_pump_shell.cc',
+              'message_pump_shell.h',
+              'native_library_shell.cc',  # Stub implementation
+              'object_watcher_shell.cc',
+              'object_watcher_shell.h',
+              'optional.cc',
+              'optional.h',
+              'optional_internal.h',
+              'shared_memory_shell.cc',  # Stub implementation
+              'state_machine_shell.h',
+              'state_machine_shell.cc',
+              'synchronization/condition_variable_shell.cc',
+              'synchronization/lock_impl_shell.cc',
+              'synchronization/waitable_event_shell.cc',
+              'threading/thread_checker_impl_atomic.cc',
+              '<!@(find <(lbshell_root)/src/platform/<(target_arch)/chromium/base -type f)',
+            ],
+            'sources!': [
+               'threading/thread_checker_impl.cc',
+            ],
+            'sources/': [
+              ['include', 'sys_string_conversions_linux.cc'],
+            ],
+          }],
+          [ 'OS=="lb_shell" and target_arch!="linux" and target_arch!="android"', {
+            'sources!': [
+              'string16.cc',  # wchar_t is 2-bytes wide, string16 == wstring here.
+            ],
+          }],
+          [ 'OS=="lb_shell" and target_arch=="android"', {
+            'sources/' : [
+              ['exclude', 'message_pump_shell.cc'],
+              ['exclude', 'message_pump_shell.h'],
+              ['exclude', 'native_library_shell.cc'],
+              ['exclude', 'process_util.cc'],
+              ['exclude', '<(lbshell_root)/src/object_watcher_shell.cc'],
+              ['exclude', '<(lbshell_root)/src/object_watcher_shell.h'],
+              ['include', 'message_pump_libevent.cc'],
+              ['include', 'message_pump_libevent.h'],
+              ['include', 'native_library_posix.cc'],
+            ],
+          }],
+          # For Starboard, we are going to build this back up as necessary.
+          ['OS=="starboard"', {
+            'sources': [
+              'base_paths_starboard.cc',
+              'circular_buffer_shell.cc',
+              'circular_buffer_shell.h',
+              'debug/debugger_starboard.cc',
+              'debug/stack_trace_starboard.cc',
+              'file_util_starboard.cc',
+              'guid_starboard.cc',
+              'message_pump_io_starboard.cc',
+              'message_pump_io_starboard.h',
+              'message_pump_ui_starboard.cc',
+              'message_pump_ui_starboard.h',
+              'optional.cc',
+              'optional.h',
+              'optional_internal.h',
+              'platform_file_starboard.cc',
+              'process_starboard.cc',
+              'process_util_starboard.cc',
+              'rand_util_starboard.cc',
+              'state_machine_shell.cc',
+              'state_machine_shell.h',
+              'synchronization/condition_variable_starboard.cc',
+              'synchronization/lock_impl_starboard.cc',
+              'synchronization/waitable_event_starboard.cc',
+              'sys_info_starboard.cc',
+              'sys_string_conversions_starboard.cc',
+              'system_monitor/system_monitor_starboard.cc',
+              'threading/platform_thread_starboard.cc',
+              'threading/thread_checker_impl_atomic.cc',
+              'threading/thread_local_starboard.cc',
+              'threading/thread_local_storage_starboard.cc',
+              'threading/worker_pool_starboard.cc',
+              'time_starboard.cc',
+            ],
+            'sources!': [
+              # Uses file_util::ReplaceFile, which isn't implemented in
+              # Starboard, and isn't otherwise used in Cobalt.
+              'files/important_file_writer.cc',
+              'files/important_file_writer.h',
+
+              # All the common functions have been removed for Starboard, so we
+              # don't even want to compile this.
+              'process_util.cc',
+
+              # Tricky to support cross-platform, and not used by Cobalt.
+              'scoped_native_library.cc',
+              'scoped_native_library.h',
+
+              # We use thread_checker_impl_atomic.cc instead.
+              'threading/thread_checker_impl.cc',
+            ],
+            'conditions': [
+              ['target_os!="linux" and target_arch!="android"', {
+                'sources!': [
+                  # Since wchar_t is 2-bytes wide, string16 == wstring here.
+                  'string16.cc',
+                ],
+              }],
+            ],
+          }],  # OS == "starboard"
+          [ 'OS=="lb_shell" or OS=="starboard"', {
+            'sources!': [
+              'environment.cc',
+              'file_descriptor_shuffle.cc',
+              'files/file_path_watcher.cc',
+              'files/file_path_watcher_kqueue.cc',
+              'files/file_path_watcher_stub.cc',
+              'message_pump_libevent.cc',
+              'message_pump_libevent.h',
+              'metrics/stats_table.cc',
+              'metrics/stats_table.h',
+            ],
+          }],  # OS == "lb_shell" or OS == "starboard"
+        ],
+        'target_conditions': [
+          ['<(use_glib)==0 or >(nacl_untrusted_build)==1', {
+              'sources/': [
+                ['exclude', '^nix/'],
+              ],
+              'sources!': [
+                'atomicops_internals_x86_gcc.cc',
+                'message_pump_glib.cc',
+                'message_pump_aurax11.cc',
+              ],
+          }],
+          ['<(toolkit_uses_gtk)==0 or >(nacl_untrusted_build)==1', {
+            'sources!': ['message_pump_gtk.cc'],
+          }],
+          ['(OS != "linux" and <(os_bsd) != 1 and OS != "android") or >(nacl_untrusted_build)==1', {
+              'sources!': [
+                # Not automatically excluded by the *linux.cc rules.
+                'linux_util.cc',
+              ],
+            },
+          ],
+          ['>(nacl_untrusted_build)==1', {
+            'sources!': [
+               'allocator/type_profiler_control.cc',
+               'allocator/type_profiler_control.h',
+               'base_paths.cc',
+               'command_line.cc',
+               'cpu.cc',
+               'debug/stack_trace_posix.cc',
+               'file_util.cc',
+               'file_util_posix.cc',
+               'file_util_proxy.cc',
+               'files/file_path_watcher_kqueue.cc',
+               'native_library_posix.cc',
+               'path_service.cc',
+               'platform_file_posix.cc',
+               'posix/unix_domain_socket.cc',
+               'process_posix.cc',
+               'process_util.cc',
+               'process_util_posix.cc',
+               'rand_util_posix.cc',
+               'scoped_native_library.cc',
+               'files/scoped_temp_dir.cc',
+               'shared_memory_posix.cc',
+               'sys_info_posix.cc',
+               'threading/sequenced_worker_pool.cc',
+               'third_party/dynamic_annotations/dynamic_annotations.c',
+            ],
+            # Metrics won't work in the NaCl sandbox.
+            'sources/': [ ['exclude', '^metrics/'] ],
+          }],
+          ['OS == "android" and >(nacl_untrusted_build)==0', {
+            'sources!': [
+              'base_paths_posix.cc',
+              'files/file_path_watcher_kqueue.cc',
+              'files/file_path_watcher_stub.cc',
+              'system_monitor/system_monitor_posix.cc',
+            ],
+            'sources/': [
+              ['include', '^files/file_path_watcher_linux\\.cc$'],
+              ['include', '^process_util_linux\\.cc$'],
+              ['include', '^sys_info_linux\\.cc$'],
+              ['include', '^sys_string_conversions_posix\\.cc$'],
+              ['include', '^worker_pool_linux\\.cc$'],
+            ],
+          }],
+          ['OS == "ios"', {
+            'sources/': [
+              # Pull in specific Mac files for iOS (which have been filtered out
+              # by file name rules).
+              ['include', '^atomicops_internals_mac\\.'],
+              ['include', '^base_paths_mac\\.'],
+              ['include', '^file_util_mac\\.'],
+              ['include', '^file_version_info_mac\\.'],
+              ['include', '^mac/bind_objc_block\\.'],
+              ['include', '^mac/bundle_locations\\.'],
+              ['include', '^mac/foundation_util\\.'],
+              ['include', '^mac/mac_logging\\.'],
+              ['include', '^mac/objc_property_releaser\\.'],
+              ['include', '^mac/scoped_mach_port\\.'],
+              ['include', '^mac/scoped_nsautorelease_pool\\.'],
+              ['include', '^message_pump_mac\\.'],
+              ['include', '^threading/platform_thread_mac\\.'],
+              ['include', '^sys_string_conversions_mac\\.'],
+              ['include', '^time_mac\\.'],
+              ['include', '^worker_pool_mac\\.'],
+              # Exclude all process_util except the minimal implementation
+              # needed on iOS (mostly for unit tests).
+              ['exclude', '^process_util'],
+              ['include', '^process_util_ios\\.mm$'],
+            ],
+            'sources!': [
+              'message_pump_libevent.cc'
+            ],
+          }],
+          ['OS != "mac" or >(nacl_untrusted_build)==1', {
+              'sources!': [
+                'mac/scoped_aedesc.h'
+              ],
+          }],
+          # For now, just test the *BSD platforms enough to exclude them.
+          # Subsequent changes will include them further.
+          ['OS != "freebsd" or >(nacl_untrusted_build)==1', {
+              'sources/': [ ['exclude', '_freebsd\\.cc$'] ],
+            },
+          ],
+          ['OS != "openbsd" or >(nacl_untrusted_build)==1', {
+              'sources/': [ ['exclude', '_openbsd\\.cc$'] ],
+            },
+          ],
+          ['OS != "win" or >(nacl_untrusted_build)==1', {
+              'sources/': [ ['exclude', '^win/'] ],
+            },
+          ],
+          ['(OS != "android" or >(nacl_untrusted_build)==1) and (OS != "lb_shell" or "<(target_arch)" != "android")', {
+              'sources/': [ ['exclude', '^android/'] ],
+            },
+          ],
+          ['OS == "win" and >(nacl_untrusted_build)==0', {
+            'include_dirs': [
+              '<(DEPTH)/third_party/wtl/include',
+            ],
+            'sources!': [
+              'event_recorder_stubs.cc',
+              'files/file_path_watcher_kqueue.cc',
+              'files/file_path_watcher_stub.cc',
+              'message_pump_libevent.cc',
+              'posix/file_descriptor_shuffle.cc',
+              # Not using sha1_win.cc because it may have caused a
+              # regression to page cycler moz.
+              'sha1_win.cc',
+              'string16.cc',
+            ],
+          },],
+          ['OS == "linux" and >(nacl_untrusted_build)==0', {
+            'sources!': [
+              'files/file_path_watcher_kqueue.cc',
+              'files/file_path_watcher_stub.cc',
+            ],
+          }],
+          ['(OS == "mac" or OS == "ios") and >(nacl_untrusted_build)==0', {
+            'sources/': [
+              ['exclude', '^files/file_path_watcher_stub\\.cc$'],
+              ['exclude', '^base_paths_posix\\.cc$'],
+              ['exclude', '^native_library_posix\\.cc$'],
+              ['exclude', '^sys_string_conversions_posix\\.cc$'],
+            ],
+          }],
+          ['<(os_bsd)==1 and >(nacl_untrusted_build)==0', {
+            'sources/': [
+              ['exclude', '^files/file_path_watcher_linux\\.cc$'],
+              ['exclude', '^files/file_path_watcher_stub\\.cc$'],
+              ['exclude', '^file_util_linux\\.cc$'],
+              ['exclude', '^process_linux\\.cc$'],
+              ['exclude', '^process_util_linux\\.cc$'],
+              ['exclude', '^sys_info_linux\\.cc$'],
+            ],
+          }],
+          ['<(chromeos)!=1 or >(nacl_untrusted_build)==1', {
+            'sources/': [
+              ['exclude', '^chromeos/'],
+            ],
+          }],
+          # Remove all unnecessary files for build_nexe.py to avoid exceeding
+          # command-line-string limitation when building NaCl on Windows.
+          ['OS == "win" and >(nacl_untrusted_build)==1', {
+              'sources/': [ ['exclude', '\\.h$'] ],
+          }],
+        ],
+      }],
+    ],
+  },
+}
diff --git a/src/base/base64.cc b/src/base/base64.cc
new file mode 100644
index 0000000..1907978
--- /dev/null
+++ b/src/base/base64.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base64.h"
+
+#include "third_party/modp_b64/modp_b64.h"
+
+namespace base {
+
+bool Base64Encode(const StringPiece& input, std::string* output) {
+  std::string temp;
+  temp.resize(modp_b64_encode_len(input.size()));  // makes room for null byte
+
+  // null terminates result since result is base64 text!
+  int input_size = static_cast<int>(input.size());
+
+  // modp_b64_encode_len() returns at least 1, so temp[0] is safe to use.
+  int output_size = modp_b64_encode(&(temp[0]), input.data(), input_size);
+  if (output_size < 0)
+    return false;
+
+  temp.resize(output_size);  // strips off null byte
+  output->swap(temp);
+  return true;
+}
+
+bool Base64Decode(const StringPiece& input, std::string* output) {
+  std::string temp;
+  temp.resize(modp_b64_decode_len(input.size()));
+
+  // does not null terminate result since result is binary data!
+  int input_size = static_cast<int>(input.size());
+  int output_size = modp_b64_decode(&(temp[0]), input.data(), input_size);
+  if (output_size < 0)
+    return false;
+
+  temp.resize(output_size);
+  output->swap(temp);
+  return true;
+}
+
+}  // namespace base
diff --git a/src/base/base64.h b/src/base/base64.h
new file mode 100644
index 0000000..983d5e2
--- /dev/null
+++ b/src/base/base64.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_BASE64_H__
+#define BASE_BASE64_H__
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/string_piece.h"
+
+namespace base {
+
+// Encodes the input string in base64.  Returns true if successful and false
+// otherwise.  The output string is only modified if successful.
+BASE_EXPORT bool Base64Encode(const StringPiece& input, std::string* output);
+
+// Decodes the base64 input string.  Returns true if successful and false
+// otherwise.  The output string is only modified if successful.
+BASE_EXPORT bool Base64Decode(const StringPiece& input, std::string* output);
+
+}  // namespace base
+
+#endif  // BASE_BASE64_H__
diff --git a/src/base/base64_unittest.cc b/src/base/base64_unittest.cc
new file mode 100644
index 0000000..9a5dd81
--- /dev/null
+++ b/src/base/base64_unittest.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base64.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+TEST(Base64Test, Basic) {
+  const std::string kText = "hello world";
+  const std::string kBase64Text = "aGVsbG8gd29ybGQ=";
+
+  std::string encoded;
+  std::string decoded;
+  bool ok;
+
+  ok = Base64Encode(kText, &encoded);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(kBase64Text, encoded);
+
+  ok = Base64Decode(encoded, &decoded);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(kText, decoded);
+}
+
+}  // namespace base
diff --git a/src/base/base_export.h b/src/base/base_export.h
new file mode 100644
index 0000000..fdfa5f9
--- /dev/null
+++ b/src/base/base_export.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_BASE_EXPORT_H_
+#define BASE_BASE_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(_MSC_VER)
+#if defined(BASE_IMPLEMENTATION)
+#define BASE_EXPORT __declspec(dllexport)
+#define BASE_EXPORT_PRIVATE __declspec(dllexport)
+#else
+#define BASE_EXPORT __declspec(dllimport)
+#define BASE_EXPORT_PRIVATE __declspec(dllimport)
+#endif  // defined(BASE_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(BASE_IMPLEMENTATION)
+#define BASE_EXPORT __attribute__((visibility("default")))
+#define BASE_EXPORT_PRIVATE __attribute__((visibility("default")))
+#else
+#define BASE_EXPORT
+#define BASE_EXPORT_PRIVATE
+#endif  // defined(BASE_IMPLEMENTATION)
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define BASE_EXPORT
+#define BASE_EXPORT_PRIVATE
+#endif
+
+#endif  // BASE_BASE_EXPORT_H_
diff --git a/src/base/base_paths.cc b/src/base/base_paths.cc
new file mode 100644
index 0000000..80105b6
--- /dev/null
+++ b/src/base/base_paths.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base_paths.h"
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+
+namespace base {
+
+bool PathProvider(int key, FilePath* result) {
+  // NOTE: DIR_CURRENT is a special case in PathService::Get
+
+  FilePath cur;
+  switch (key) {
+    case base::DIR_EXE:
+      PathService::Get(base::FILE_EXE, &cur);
+      cur = cur.DirName();
+      break;
+    case base::DIR_MODULE:
+      PathService::Get(base::FILE_MODULE, &cur);
+      cur = cur.DirName();
+      break;
+    case base::DIR_TEMP:
+      if (!file_util::GetTempDir(&cur))
+        return false;
+      break;
+    default:
+      return false;
+  }
+
+  *result = cur;
+  return true;
+}
+
+}  // namespace base
diff --git a/src/base/base_paths.h b/src/base/base_paths.h
new file mode 100644
index 0000000..7bc23a8
--- /dev/null
+++ b/src/base/base_paths.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_BASE_PATHS_H_
+#define BASE_BASE_PATHS_H_
+
+// This file declares path keys for the base module.  These can be used with
+// the PathService to access various special directories and files.
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "base/base_paths_win.h"
+#elif defined(OS_MACOSX)
+#include "base/base_paths_mac.h"
+#elif defined(OS_ANDROID) || defined(__LB_ANDROID__)
+#include "base/base_paths_android.h"
+#elif defined(OS_STARBOARD)
+#include "base/base_paths_starboard.h"
+#endif
+
+#if defined(OS_POSIX)
+#include "base/base_paths_posix.h"
+#endif
+
+namespace base {
+