Revved to chromium 7f6805bd9257180e07cb6924ea41bcb76cfa462b refs/remotes/origin/HEAD

filter gyp out of build/landmines.py

filter pepper out of mojo/examples/BUILD.gn

filter html_viewer out of mojo/services/BUILD.gn

filter js out of mojo/BUILD.gn

filter js/bindings out of mojo/public/BUILD.gn

applied patch gpu_media.patch

applied patch cc_strip_video.patch

applied patch ui_test_support.patch

applied patch remove_ipc_deps.patch

applied patch ui_compositor.patch

applied patch net_sql.patch
diff --git a/BUILD.gn b/BUILD.gn
index 18f2b01..d783ee0 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1227,6 +1227,7 @@
     "process/memory_unittest_mac.mm",
     "process/process_metrics_unittest.cc",
     "process/process_metrics_unittest_ios.cc",
+    "process/process_unittest.cc",
     "process/process_util_unittest.cc",
     "process/process_util_unittest_ios.cc",
     "profiler/tracked_time_unittest.cc",
@@ -1338,6 +1339,7 @@
       "process/memory_unittest.cc",
       "process/memory_unittest_mac.h",
       "process/memory_unittest_mac.mm",
+      "process/process_unittest.cc",
       "process/process_util_unittest.cc",
     ]
 
diff --git a/OWNERS b/OWNERS
index 04e7a6f..a014c74 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,12 +1,14 @@
 mark@chromium.org
 darin@chromium.org
-willchan@chromium.org
 ajwong@chromium.org
 thakis@chromium.org
 danakj@chromium.org
 rvargas@chromium.org
 thestig@chromium.org
 
+# On extended leave.
+willchan@chromium.org
+
 per-file *.isolate=csharp@chromium.org
 per-file *.isolate=maruel@chromium.org
 per-file bind.h=ajwong@chromium.org
diff --git a/android/BUILD.gn b/android/BUILD.gn
new file mode 100644
index 0000000..befe397
--- /dev/null
+++ b/android/BUILD.gn
@@ -0,0 +1,18 @@
+import("//build/config/android/config.gni")
+
+assert(is_android)
+assert(!is_android_webview_build)
+
+shared_library("chromium_android_linker") {
+  sources = [ "linker/linker_jni.cc" ]
+  # The NDK contains the crazy_linker here:
+  #   '<(android_ndk_root)/crazy_linker.gyp:crazy_linker'
+  # However, we use our own fork.  See bug 384700.
+  deps = [ "//third_party/android_crazy_linker" ]
+
+  # TODO(GYP):
+  # The crazy linker is never instrumented.
+  #'cflags!': [
+  #'-finstrument-functions',
+  #],
+}
diff --git a/android/java/src/org/chromium/base/library_loader/Linker.java b/android/java/src/org/chromium/base/library_loader/Linker.java
index 2b3cb09..41104f0 100644
--- a/android/java/src/org/chromium/base/library_loader/Linker.java
+++ b/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -826,7 +826,7 @@
                 sCurrentLoadAddress = libInfo.mLoadAddress + libInfo.mLoadSize;
             }
 
-            sLoadedLibraries.put(libName, libInfo);
+            sLoadedLibraries.put(sharedRelRoName, libInfo);
             if (DEBUG) Log.i(TAG, "Library details " + libInfo.toString());
         }
     }
diff --git a/base.gyp b/base.gyp
index 41fac4f..95f6f7d 100644
--- a/base.gyp
+++ b/base.gyp
@@ -564,6 +564,7 @@
         'process/memory_unittest_mac.mm',
         'process/process_metrics_unittest.cc',
         'process/process_metrics_unittest_ios.cc',
+        'process/process_unittest.cc',
         'process/process_util_unittest.cc',
         'profiler/tracked_time_unittest.cc',
         'rand_util_unittest.cc',
@@ -683,6 +684,7 @@
           'sources/': [
             # Only test the iOS-meaningful portion of process_utils.
             ['exclude', '^process/memory_unittest'],
+            ['exclude', '^process/process_unittest\\.cc$'],
             ['exclude', '^process/process_util_unittest\\.cc$'],
             ['include', '^process/process_util_unittest_ios\\.cc$'],
             # Requires spawning processes.
@@ -1404,7 +1406,7 @@
           'includes': [ '../build/java.gypi' ],
         },
         {
-          # TODO(GN)
+          # GN: //base/android/chromium_android_linker
           'target_name': 'chromium_android_linker',
           'type': 'shared_library',
           'conditions': [
diff --git a/base_nacl.gyp b/base_nacl.gyp
index 0816d31..7221d2a 100644
--- a/base_nacl.gyp
+++ b/base_nacl.gyp
@@ -67,5 +67,60 @@
         },
       ],
     }],
+    ['disable_nacl==0', {
+      'targets': [
+        {
+          'target_name': 'base_nacl_nonsfi',
+          'type': 'none',
+          'include_dirs': [
+            '<(DEPTH)/native_client/src/public/linux_syscalls',
+          ],
+          'variables': {
+            'base_target': 1,
+            'nacl_untrusted_build': 1,
+            'nlib_target': 'libbase_nacl_nonsfi.a',
+            'build_glibc': 0,
+            'build_newlib': 0,
+            'build_irt': 0,
+            'build_pnacl_newlib': 0,
+            'build_nonsfi_helper': 1,
+
+            'sources': [
+              'base_switches.cc',
+              'base_switches.h',
+
+              # For PathExists and ReadFromFD.
+              'files/file_util_posix.cc',
+
+              # For MessageLoopForIO based on libevent.
+              'message_loop/message_pump_libevent.cc',
+              'message_loop/message_pump_libevent.h',
+
+              # For UnixDomainSocket::SendMsg and RecvMsg.
+              'posix/unix_domain_socket_linux.cc',
+
+              # For GetKnownDeadTerminationStatus and GetTerminationStatus.
+              'process/kill_posix.cc',
+
+              # Unlike libbase_nacl, for Non-SFI build, we need to use
+              # rand_util_posix for random implementation, instead of
+              # rand_util_nacl.cc, which is based on IRT. rand_util_nacl.cc is
+              # excluded below.
+              'rand_util_posix.cc',
+
+              # For CancelableSyncSocket.
+              'sync_socket_nacl.cc',
+            ],
+          },
+          'sources!': [
+            'rand_util_nacl.cc',
+          ],
+          'dependencies': [
+            '<(DEPTH)/native_client/tools.gyp:prep_toolchain',
+            '<(DEPTH)/third_party/libevent/libevent_nacl_nonsfi.gyp:event_nacl_nonsfi',
+          ],
+        },
+      ],
+    }],
   ],
 }
diff --git a/build_time.cc b/build_time.cc
index 760269a..86503e2 100644
--- a/build_time.cc
+++ b/build_time.cc
@@ -16,7 +16,11 @@
   //
   // __DATE__ is exactly "Mmm DD YYYY".
   // __TIME__ is exactly "hh:mm:ss".
+#if defined(DONT_EMBED_BUILD_METADATA)
+  const char kDateTime[] = "Sep 02 2008 08:00:00 PST";
+#else
   const char kDateTime[] = __DATE__ " " __TIME__ " PST";
+#endif
   bool result = Time::FromString(kDateTime, &integral_build_time);
   DCHECK(result);
   return integral_build_time;
diff --git a/build_time_unittest.cc b/build_time_unittest.cc
index 399a53f..aac64a7 100644
--- a/build_time_unittest.cc
+++ b/build_time_unittest.cc
@@ -7,7 +7,11 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(BuildTime, DateLooksValid) {
+#if !defined(DONT_EMBED_BUILD_METADATA)
   char build_date[] = __DATE__;
+#else
+  char build_date[] = "Sep 02 2008";
+#endif
 
   EXPECT_EQ(11u, strlen(build_date));
   EXPECT_EQ(' ', build_date[3]);
@@ -15,7 +19,11 @@
 }
 
 TEST(BuildTime, TimeLooksValid) {
+#if defined(DONT_EMBED_BUILD_METADATA)
+  char build_time[] = "08:00:00";
+#else
   char build_time[] = __TIME__;
+#endif
 
   EXPECT_EQ(8u, strlen(build_time));
   EXPECT_EQ(':', build_time[2]);
diff --git a/compiler_specific.h b/compiler_specific.h
index ba57cc3..6210d1a 100644
--- a/compiler_specific.h
+++ b/compiler_specific.h
@@ -94,11 +94,17 @@
 // (Typically used to silence a compiler warning when the assignment
 // is important for some other reason.)
 // Use like:
-//   int x ALLOW_UNUSED = ...;
+//   int x = ...;
+//   ALLOW_UNUSED_LOCAL(x);
+#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0
+
+// Annotate a typedef or function indicating it's ok if it's not used.
+// Use like:
+//   typedef Foo Bar ALLOW_UNUSED_TYPE;
 #if defined(COMPILER_GCC)
-#define ALLOW_UNUSED __attribute__((unused))
+#define ALLOW_UNUSED_TYPE __attribute__((unused))
 #else
-#define ALLOW_UNUSED
+#define ALLOW_UNUSED_TYPE
 #endif
 
 // Annotate a function indicating it should not be inlined.
diff --git a/files/file_util_posix.cc b/files/file_util_posix.cc
index 561f5c7..5a94cef 100644
--- a/files/file_util_posix.cc
+++ b/files/file_util_posix.cc
@@ -59,6 +59,7 @@
 
 namespace base {
 
+#if !defined(__native_client_nonsfi__)
 namespace {
 
 #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
@@ -345,6 +346,7 @@
 
   return success;
 }
+#endif  // !defined(__native_client_nonsfi__)
 
 bool PathExists(const FilePath& path) {
   ThreadRestrictions::AssertIOAllowed();
@@ -356,6 +358,7 @@
   return access(path.value().c_str(), F_OK) == 0;
 }
 
+#if !defined(__native_client_nonsfi__)
 bool PathIsWritable(const FilePath& path) {
   ThreadRestrictions::AssertIOAllowed();
   return access(path.value().c_str(), W_OK) == 0;
@@ -368,6 +371,7 @@
     return S_ISDIR(file_info.st_mode);
   return false;
 }
+#endif  // !defined(__native_client_nonsfi__)
 
 bool ReadFromFD(int fd, char* buffer, size_t bytes) {
   size_t total_read = 0;
@@ -381,6 +385,7 @@
   return total_read == bytes;
 }
 
+#if !defined(__native_client_nonsfi__)
 bool CreateSymbolicLink(const FilePath& target_path,
                         const FilePath& symlink_path) {
   DCHECK(!symlink_path.empty());
@@ -920,4 +925,6 @@
 #endif  // !defined(OS_MACOSX)
 
 }  // namespace internal
+
+#endif  // !defined(__native_client_nonsfi__)
 }  // namespace base
diff --git a/logging_unittest.cc b/logging_unittest.cc
index 6ebe32e..95a16f2 100644
--- a/logging_unittest.cc
+++ b/logging_unittest.cc
@@ -240,7 +240,8 @@
 // looking in the global namespace.
 namespace nested_test {
   class Streamable {};
-  ALLOW_UNUSED std::ostream& operator<<(std::ostream& out, const Streamable&) {
+  ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out,
+                                             const Streamable&) {
     return out << "Streamable";
   }
   TEST_F(LoggingTest, StreamingWstringFindsCorrectOperator) {
diff --git a/mac/foundation_util_unittest.mm b/mac/foundation_util_unittest.mm
index 916a13b..e60a0f6 100644
--- a/mac/foundation_util_unittest.mm
+++ b/mac/foundation_util_unittest.mm
@@ -331,12 +331,12 @@
 #endif  // defined(ARCH_CPU_64_BITS)
 
   NSInteger some_nsinteger;
-  FormatNSIntegerAsType* pointer_to_some_nsinteger ALLOW_UNUSED =
-      &some_nsinteger;
+  FormatNSIntegerAsType* pointer_to_some_nsinteger = &some_nsinteger;
+  ALLOW_UNUSED_LOCAL(pointer_to_some_nsinteger);
 
   NSUInteger some_nsuinteger;
-  FormatNSUIntegerAsType* pointer_to_some_nsuinteger ALLOW_UNUSED =
-      &some_nsuinteger;
+  FormatNSUIntegerAsType* pointer_to_some_nsuinteger = &some_nsuinteger;
+  ALLOW_UNUSED_LOCAL(pointer_to_some_nsuinteger);
 
   // Check that format specifier works correctly for NSInteger.
   const struct {
diff --git a/macros.h b/macros.h
index 2e3fc09..f89d7d1 100644
--- a/macros.h
+++ b/macros.h
@@ -69,8 +69,12 @@
 
 // DEPRECATED: Just use |arraysize()|, now that C++11 has removed the
 // limitations that forced the use of |ARRAYSIZE_UNSAFE()|.
-// TODO(viettrungluu): Convert all instances and delete. crbug.com/423134
+// TODO(viettrungluu): Convert all instances and delete. (The only uses are now
+// in Blink; the ifdef is to prevent it from reappearing in Chromium.)
+// crbug.com/423134
+#if defined(BLINK_PLATFORM) || defined(BLINK_PLATFORM_IMPLEMENTATION)
 #define ARRAYSIZE_UNSAFE(a) arraysize(a)
+#endif
 
 
 // Use implicit_cast as a safe version of static_cast or const_cast
diff --git a/memory/discardable_memory_unittest.cc b/memory/discardable_memory_unittest.cc
index 2bdc079..600475e 100644
--- a/memory/discardable_memory_unittest.cc
+++ b/memory/discardable_memory_unittest.cc
@@ -103,6 +103,22 @@
 }
 #endif
 
+// Test behavior when creating enough instances that could use up a 32-bit
+// address space.
+TEST_P(DiscardableMemoryTest, AddressSpace) {
+  const size_t kLargeSize = 4 * 1024 * 1024;  // 4MiB.
+  const size_t kNumberOfInstances = 1024 + 1;  // >4GiB total.
+
+  scoped_ptr<DiscardableMemory> instances[kNumberOfInstances];
+  for (auto& memory : instances) {
+    memory = CreateLockedMemory(kLargeSize);
+    ASSERT_TRUE(memory);
+    void* addr = memory->Memory();
+    ASSERT_NE(nullptr, addr);
+    memory->Unlock();
+  }
+}
+
 std::vector<DiscardableMemoryType> GetSupportedDiscardableMemoryTypes() {
   std::vector<DiscardableMemoryType> supported_types;
   DiscardableMemory::GetSupportedTypes(&supported_types);
diff --git a/message_loop/message_loop.cc b/message_loop/message_loop.cc
index c01e542..f1d0d3b 100644
--- a/message_loop/message_loop.cc
+++ b/message_loop/message_loop.cc
@@ -100,7 +100,7 @@
 
 #if defined(OS_IOS)
 typedef MessagePumpIOSForIO MessagePumpForIO;
-#elif defined(OS_NACL)
+#elif defined(OS_NACL) && !defined(__native_client_nonsfi__)
 typedef MessagePumpDefault MessagePumpForIO;
 #elif defined(OS_POSIX)
 typedef MessagePumpLibevent MessagePumpForIO;
@@ -676,7 +676,7 @@
 //------------------------------------------------------------------------------
 // MessageLoopForIO
 
-#if !defined(OS_NACL)
+#if !defined(OS_NACL) || defined(__native_client_nonsfi__)
 void MessageLoopForIO::AddIOObserver(
     MessageLoopForIO::IOObserver* io_observer) {
   ToPumpIO(pump_.get())->AddIOObserver(io_observer);
@@ -714,6 +714,6 @@
 }
 #endif
 
-#endif  // !defined(OS_NACL)
+#endif  // !defined(OS_NACL) || defined(__native_client_nonsfi__)
 
 }  // namespace base
diff --git a/message_loop/message_loop.h b/message_loop/message_loop.h
index bc98251..a180cc3 100644
--- a/message_loop/message_loop.h
+++ b/message_loop/message_loop.h
@@ -596,7 +596,7 @@
     return loop && loop->type() == MessageLoop::TYPE_IO;
   }
 
-#if !defined(OS_NACL)
+#if !defined(OS_NACL) || defined(__native_client_nonsfi__)
 
 #if defined(OS_WIN)
   typedef MessagePumpForIO::IOHandler IOHandler;
@@ -642,7 +642,7 @@
                            FileDescriptorWatcher *controller,
                            Watcher *delegate);
 #endif  // defined(OS_IOS) || defined(OS_POSIX)
-#endif  // !defined(OS_NACL)
+#endif  // !defined(OS_NACL) || defined(__native_client_nonsfi__)
 };
 
 // Do not add any member variables to MessageLoopForIO!  This is important b/c
diff --git a/posix/unix_domain_socket_linux.cc b/posix/unix_domain_socket_linux.cc
index 51b936b..20a5944 100644
--- a/posix/unix_domain_socket_linux.cc
+++ b/posix/unix_domain_socket_linux.cc
@@ -6,7 +6,6 @@
 
 #include <errno.h>
 #include <sys/socket.h>
-#include <sys/uio.h>
 #include <unistd.h>
 
 #include <vector>
@@ -18,8 +17,13 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/stl_util.h"
 
+#if !defined(__native_client_nonsfi__)
+#include <sys/uio.h>
+#endif
+
 const size_t UnixDomainSocket::kMaxFileDescriptors = 16;
 
+#if !defined(__native_client_nonsfi__)
 // Creates a connected pair of UNIX-domain SOCK_SEQPACKET sockets, and passes
 // ownership of the newly allocated file descriptors to |one| and |two|.
 // Returns true on success.
@@ -37,6 +41,7 @@
   const int enable = 1;
   return setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)) == 0;
 }
+#endif  // !defined(__native_client_nonsfi__)
 
 // static
 bool UnixDomainSocket::SendMsg(int fd,
@@ -106,8 +111,14 @@
   msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
 
-  char control_buffer[CMSG_SPACE(sizeof(int) * kMaxFileDescriptors) +
-                      CMSG_SPACE(sizeof(struct ucred))];
+  const size_t kControlBufferSize =
+      CMSG_SPACE(sizeof(int) * kMaxFileDescriptors)
+#if !defined(__native_client_nonsfi__)
+      // The PNaCl toolchain for Non-SFI binary build does not support ucred.
+      + CMSG_SPACE(sizeof(struct ucred))
+#endif
+      ;
+  char control_buffer[kControlBufferSize];
   msg.msg_control = control_buffer;
   msg.msg_controllen = sizeof(control_buffer);
 
@@ -130,21 +141,29 @@
         wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
         wire_fds_len = payload_len / sizeof(int);
       }
+#if !defined(__native_client_nonsfi__)
+      // The PNaCl toolchain for Non-SFI binary build does not support
+      // SCM_CREDENTIALS.
       if (cmsg->cmsg_level == SOL_SOCKET &&
           cmsg->cmsg_type == SCM_CREDENTIALS) {
         DCHECK(payload_len == sizeof(struct ucred));
         DCHECK(pid == -1);
         pid = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg))->pid;
       }
+#endif
     }
   }
 
+#if !defined(__native_client_nonsfi__)
+  // The PNaCl toolchain for Non-SFI binary build does not support
+  // MSG_TRUNC or MSG_CTRUNC.
   if (msg.msg_flags & MSG_TRUNC || msg.msg_flags & MSG_CTRUNC) {
     for (unsigned i = 0; i < wire_fds_len; ++i)
       close(wire_fds[i]);
     errno = EMSGSIZE;
     return -1;
   }
+#endif
 
   if (wire_fds) {
     for (unsigned i = 0; i < wire_fds_len; ++i)
@@ -165,6 +184,7 @@
   return r;
 }
 
+#if !defined(__native_client_nonsfi__)
 // static
 ssize_t UnixDomainSocket::SendRecvMsg(int fd,
                                       uint8_t* reply,
@@ -222,3 +242,4 @@
 
   return reply_len;
 }
+#endif  // !defined(__native_client_nonsfi__)
diff --git a/posix/unix_domain_socket_linux.h b/posix/unix_domain_socket_linux.h
index 59bb884..5281875 100644
--- a/posix/unix_domain_socket_linux.h
+++ b/posix/unix_domain_socket_linux.h
@@ -21,10 +21,12 @@
   // Maximum number of file descriptors that can be read by RecvMsg().
   static const size_t kMaxFileDescriptors;
 
+#if !defined(__native_client_nonsfi__)
   // Use to enable receiving process IDs in RecvMsgWithPid.  Should be called on
   // the receiving socket (i.e., the socket passed to RecvMsgWithPid). Returns
   // true if successful.
   static bool EnableReceiveProcessId(int fd);
+#endif  // !defined(__native_client_nonsfi__)
 
   // Use sendmsg to write the given msg and include a vector of file
   // descriptors. Returns true if successful.
@@ -50,6 +52,7 @@
                                 ScopedVector<base::ScopedFD>* fds,
                                 base::ProcessId* pid);
 
+#if !defined(__native_client_nonsfi__)
   // Perform a sendmsg/recvmsg pair.
   //   1. This process creates a UNIX SEQPACKET socketpair. Using
   //      connection-oriented sockets (SEQPACKET or STREAM) is critical here,
@@ -82,6 +85,7 @@
                                       int recvmsg_flags,
                                       int* result_fd,
                                       const Pickle& request);
+#endif  // !defined(__native_client_nonsfi__)
  private:
   // Similar to RecvMsg, but allows to specify |flags| for recvmsg(2).
   static ssize_t RecvMsgWithFlags(int fd,
diff --git a/process/kill_posix.cc b/process/kill_posix.cc
index d4ca726..bff7be4 100644
--- a/process/kill_posix.cc
+++ b/process/kill_posix.cc
@@ -22,6 +22,7 @@
 
 namespace {
 
+#if !defined(__native_client_nonsfi__)
 bool WaitpidWithTimeout(ProcessHandle handle,
                         int* status,
                         base::TimeDelta wait) {
@@ -83,6 +84,7 @@
 
   return ret_pid > 0;
 }
+#endif  // !defined(__native_client_nonsfi__)
 
 TerminationStatus GetTerminationStatusImpl(ProcessHandle handle,
                                            bool can_block,
@@ -130,6 +132,7 @@
 
 }  // namespace
 
+#if !defined(__native_client_nonsfi__)
 // Attempts to kill the process identified by the given process
 // entry structure.  Ignores specified exit_code; posix can't force that.
 // Returns true if this is successful, false otherwise.
@@ -191,6 +194,7 @@
     DPLOG(ERROR) << "Unable to terminate process group " << process_group_id;
   return result;
 }
+#endif  // !defined(__native_client_nonsfi__)
 
 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
   return GetTerminationStatusImpl(handle, false /* can_block */, exit_code);
@@ -206,6 +210,7 @@
   return GetTerminationStatusImpl(handle, true /* can_block */, exit_code);
 }
 
+#if !defined(__native_client_nonsfi__)
 bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
   int status;
   if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
@@ -354,7 +359,7 @@
 
 bool WaitForSingleProcess(ProcessHandle handle, base::TimeDelta wait) {
   ProcessHandle parent_pid = GetParentProcessId(handle);
-  ProcessHandle our_pid = Process::Current().handle();
+  ProcessHandle our_pid = GetCurrentProcessHandle();
   if (parent_pid != our_pid) {
 #if defined(OS_MACOSX)
     // On Mac we can wait on non child processes.
@@ -478,5 +483,6 @@
 }
 
 #endif  // !defined(OS_MACOSX)
+#endif  // !defined(__native_client_nonsfi__)
 
 }  // namespace base
diff --git a/process/process.h b/process/process.h
index 20e8884..7019474 100644
--- a/process/process.h
+++ b/process/process.h
@@ -7,53 +7,81 @@
 
 #include "base/base_export.h"
 #include "base/basictypes.h"
+#include "base/move.h"
 #include "base/process/process_handle.h"
 #include "build/build_config.h"
 
+#if defined(OS_WIN)
+#include "base/win/scoped_handle.h"
+#endif
+
 namespace base {
 
+// Provides a move-only encapsulation of a process.
+//
+// This object is not tied to the lifetime of the underlying process: the
+// process may be killed and this object may still around, and it will still
+// claim to be valid. The actual behavior in that case is OS dependent like so:
+//
+// Windows: The underlying ProcessHandle will be valid after the process dies
+// and can be used to gather some information about that process, but most
+// methods will obviously fail.
+//
+// POSIX: The underlying PorcessHandle is not guaranteed to remain valid after
+// the process dies, and it may be reused by the system, which means that it may
+// end up pointing to the wrong process.
 class BASE_EXPORT Process {
+  MOVE_ONLY_TYPE_FOR_CPP_03(Process, RValue)
+
  public:
-  Process() : process_(kNullProcessHandle) {
-  }
+  explicit Process(ProcessHandle handle = kNullProcessHandle);
 
-  explicit Process(ProcessHandle handle) : process_(handle) {
-  }
+  // Move constructor for C++03 move emulation of this type.
+  Process(RValue other);
 
-  // A handle to the current process.
+  // The destructor does not terminate the process.
+  ~Process() {}
+
+  // Move operator= for C++03 move emulation of this type.
+  Process& operator=(RValue other);
+
+  // Returns an object for the current process.
   static Process Current();
 
+  // Returns true if processes can be backgrounded.
   static bool CanBackgroundProcesses();
 
-  // Get/Set the handle for this process. The handle will be 0 if the process
-  // is no longer running.
-  ProcessHandle handle() const { return process_; }
-  void set_handle(ProcessHandle handle) {
-    process_ = handle;
-  }
+  // Returns true if this objects represents a valid process.
+  bool IsValid() const;
+
+  // Returns a handle for this process. There is no guarantee about when that
+  // handle becomes invalid because this object retains ownership.
+  ProcessHandle Handle() const;
+
+  // Returns a second object that represents this process.
+  Process Duplicate() const;
 
   // Get the PID for this process.
   ProcessId pid() const;
 
-  // Is the this process the current process.
+  // Returns true if this process is the current process.
   bool is_current() const;
 
   // Close the process handle. This will not terminate the process.
   void Close();
 
-  // Terminates the process with extreme prejudice. The given result code will
-  // be the exit code of the process. If the process has already exited, this
-  // will do nothing.
+  // Terminates the process with extreme prejudice. The given |result_code| will
+  // be the exit code of the process.
+  // NOTE: On POSIX |result_code| is ignored.
   void Terminate(int result_code);
 
   // A process is backgrounded when it's priority is lower than normal.
   // Return true if this process is backgrounded, false otherwise.
   bool IsProcessBackgrounded() const;
 
-  // Set a process as backgrounded. If value is true, the priority
-  // of the process will be lowered. If value is false, the priority
-  // of the process will be made "normal" - equivalent to default
-  // process priority.
+  // Set a process as backgrounded. If value is true, the priority of the
+  // process will be lowered. If value is false, the priority of the process
+  // will be made "normal" - equivalent to default process priority.
   // Returns true if the priority was changed, false otherwise.
   bool SetProcessBackgrounded(bool value);
 
@@ -62,7 +90,12 @@
   int GetPriority() const;
 
  private:
+#if defined(OS_WIN)
+  bool is_current_process_;
+  win::ScopedHandle process_;
+#else
   ProcessHandle process_;
+#endif
 };
 
 }  // namespace base
diff --git a/process/process_linux.cc b/process/process_linux.cc
index 2c22d26..59ee288 100644
--- a/process/process_linux.cc
+++ b/process/process_linux.cc
@@ -17,6 +17,7 @@
 namespace base {
 
 namespace {
+
 const int kForegroundPriority = 0;
 
 #if defined(OS_CHROMEOS)
@@ -62,10 +63,37 @@
 #else
 const int kBackgroundPriority = 5;
 #endif
+
+struct CheckForNicePermission {
+  CheckForNicePermission() : can_reraise_priority(false) {
+    // We won't be able to raise the priority if we don't have the right rlimit.
+    // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
+    struct rlimit rlim;
+    if ((getrlimit(RLIMIT_NICE, &rlim) == 0) &&
+        (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) {
+        can_reraise_priority = true;
+    }
+  };
+
+  bool can_reraise_priority;
+};
+
+}  // namespace
+
+// static
+bool Process::CanBackgroundProcesses() {
+#if defined(OS_CHROMEOS)
+  if (cgroups.Get().enabled)
+    return true;
+#endif
+
+  static LazyInstance<CheckForNicePermission> check_for_nice_permission =
+      LAZY_INSTANCE_INITIALIZER;
+  return check_for_nice_permission.Get().can_reraise_priority;
 }
 
 bool Process::IsProcessBackgrounded() const {
-  DCHECK(process_);
+  DCHECK(IsValid());
 
 #if defined(OS_CHROMEOS)
   if (cgroups.Get().enabled) {
@@ -87,7 +115,7 @@
 }
 
 bool Process::SetProcessBackgrounded(bool background) {
-  DCHECK(process_);
+  DCHECK(IsValid());
 
 #if defined(OS_CHROMEOS)
   if (cgroups.Get().enabled) {
@@ -108,30 +136,4 @@
   return result == 0;
 }
 
-struct CheckForNicePermission {
-  CheckForNicePermission() : can_reraise_priority(false) {
-    // We won't be able to raise the priority if we don't have the right rlimit.
-    // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
-    struct rlimit rlim;
-    if ((getrlimit(RLIMIT_NICE, &rlim) == 0) &&
-        (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) {
-        can_reraise_priority = true;
-    }
-  };
-
-  bool can_reraise_priority;
-};
-
-// static
-bool Process::CanBackgroundProcesses() {
-#if defined(OS_CHROMEOS)
-  if (cgroups.Get().enabled)
-    return true;
-#endif
-
-  static LazyInstance<CheckForNicePermission> check_for_nice_permission =
-      LAZY_INSTANCE_INITIALIZER;
-  return check_for_nice_permission.Get().can_reraise_priority;
-}
-
 }  // namespace base
diff --git a/process/process_posix.cc b/process/process_posix.cc
index 3d8b31d..ea8fd8c 100644
--- a/process/process_posix.cc
+++ b/process/process_posix.cc
@@ -13,15 +13,54 @@
 
 namespace base {
 
+Process::Process(ProcessHandle handle) : process_(handle) {
+  CHECK_NE(handle, GetCurrentProcessHandle());
+}
+
+Process::Process(RValue other)
+    : process_(other.object->process_) {
+  other.object->Close();
+}
+
+Process& Process::operator=(RValue other) {
+  if (this != other.object) {
+    process_ = other.object->process_;
+    other.object->Close();
+  }
+  return *this;
+}
+
 // static
 Process Process::Current() {
-  return Process(GetCurrentProcessHandle());
+  Process process;
+  process.process_ = GetCurrentProcessHandle();
+  return process.Pass();
+}
+
+#if !defined(OS_LINUX)
+// static
+bool Process::CanBackgroundProcesses() {
+  return false;
+}
+#endif  // !defined(OS_LINUX)
+
+bool Process::IsValid() const {
+  return process_ != kNullProcessHandle;
+}
+
+ProcessHandle Process::Handle() const {
+  return process_;
+}
+
+Process Process::Duplicate() const {
+  if (is_current())
+    return Current();
+
+  return Process(process_);
 }
 
 ProcessId Process::pid() const {
-  if (process_ == 0)
-    return 0;
-
+  DCHECK(IsValid());
   return GetProcId(process_);
 }
 
@@ -30,7 +69,7 @@
 }
 
 void Process::Close() {
-  process_ = 0;
+  process_ = kNullProcessHandle;
   // if the process wasn't terminated (so we waited) or the state
   // wasn't already collected w/ a wait from process_utils, we're gonna
   // end up w/ a zombie when it does finally exit.
@@ -38,8 +77,7 @@
 
 void Process::Terminate(int result_code) {
   // result_code isn't supportable.
-  if (!process_)
-    return;
+  DCHECK(IsValid());
   // We don't wait here. It's the responsibility of other code to reap the
   // child.
   KillProcess(process_, result_code, false);
@@ -48,6 +86,7 @@
 #if !defined(OS_LINUX)
 bool Process::IsProcessBackgrounded() const {
   // See SetProcessBackgrounded().
+  DCHECK(IsValid());
   return false;
 }
 
@@ -55,18 +94,13 @@
   // POSIX only allows lowering the priority of a process, so if we
   // were to lower it we wouldn't be able to raise it back to its initial
   // priority.
+  DCHECK(IsValid());
   return false;
 }
-
-// static
-bool Process::CanBackgroundProcesses() {
-  return false;
-}
-
-#endif
+#endif  // !defined(OS_LINUX)
 
 int Process::GetPriority() const {
-  DCHECK(process_);
+  DCHECK(IsValid());
   return getpriority(PRIO_PROCESS, process_);
 }
 
diff --git a/process/process_unittest.cc b/process/process_unittest.cc
new file mode 100644
index 0000000..66d6e63
--- /dev/null
+++ b/process/process_unittest.cc
@@ -0,0 +1,161 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/process/process.h"
+
+#include "base/process/kill.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/platform_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
+
+
+namespace {
+
+#if defined(OS_WIN)
+const int kExpectedStillRunningExitCode = 0x102;
+#else
+const int kExpectedStillRunningExitCode = 0;
+#endif
+
+}  // namespace
+
+namespace base {
+
+class ProcessTest : public MultiProcessTest {
+};
+
+TEST_F(ProcessTest, Create) {
+  Process process(SpawnChild("SimpleChildProcess"));
+  ASSERT_TRUE(process.IsValid());
+  ASSERT_FALSE(process.is_current());
+  process.Close();
+  ASSERT_FALSE(process.IsValid());
+}
+
+TEST_F(ProcessTest, CreateCurrent) {
+  Process process = Process::Current();
+  ASSERT_TRUE(process.IsValid());
+  ASSERT_TRUE(process.is_current());
+  process.Close();
+  ASSERT_FALSE(process.IsValid());
+}
+
+TEST_F(ProcessTest, Move) {
+  Process process1(SpawnChild("SimpleChildProcess"));
+  EXPECT_TRUE(process1.IsValid());
+
+  Process process2;
+  EXPECT_FALSE(process2.IsValid());
+
+  process2 = process1.Pass();
+  EXPECT_TRUE(process2.IsValid());
+  EXPECT_FALSE(process1.IsValid());
+  EXPECT_FALSE(process2.is_current());
+
+  Process process3 = Process::Current();
+  process2 = process3.Pass();
+  EXPECT_TRUE(process2.is_current());
+  EXPECT_TRUE(process2.IsValid());
+  EXPECT_FALSE(process3.IsValid());
+}
+
+TEST_F(ProcessTest, Duplicate) {
+  Process process1(SpawnChild("SimpleChildProcess"));
+  ASSERT_TRUE(process1.IsValid());
+
+  Process process2 = process1.Duplicate();
+  ASSERT_TRUE(process1.IsValid());
+  ASSERT_TRUE(process2.IsValid());
+  EXPECT_EQ(process1.pid(), process2.pid());
+  EXPECT_FALSE(process1.is_current());
+  EXPECT_FALSE(process2.is_current());
+
+  process1.Close();
+  ASSERT_TRUE(process2.IsValid());
+}
+
+TEST_F(ProcessTest, DuplicateCurrent) {
+  Process process1 = Process::Current();
+  ASSERT_TRUE(process1.IsValid());
+
+  Process process2 = process1.Duplicate();
+  ASSERT_TRUE(process1.IsValid());
+  ASSERT_TRUE(process2.IsValid());
+  EXPECT_EQ(process1.pid(), process2.pid());
+  EXPECT_TRUE(process1.is_current());
+  EXPECT_TRUE(process2.is_current());
+
+  process1.Close();
+  ASSERT_TRUE(process2.IsValid());
+}
+
+MULTIPROCESS_TEST_MAIN(SleepyChildProcess) {
+  PlatformThread::Sleep(TestTimeouts::action_max_timeout());
+  return 0;
+}
+
+TEST_F(ProcessTest, Terminate) {
+  Process process(SpawnChild("SleepyChildProcess"));
+  ASSERT_TRUE(process.IsValid());
+
+  const int kDummyExitCode = 42;
+  int exit_code = kDummyExitCode;
+  EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
+            GetTerminationStatus(process.Handle(), &exit_code));
+  EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
+
+  exit_code = kDummyExitCode;
+  int kExpectedExitCode = 250;
+  process.Terminate(kExpectedExitCode);
+  WaitForSingleProcess(process.Handle(), TestTimeouts::action_max_timeout());
+
+  EXPECT_NE(TERMINATION_STATUS_STILL_RUNNING,
+            GetTerminationStatus(process.Handle(), &exit_code));
+#if !defined(OS_POSIX)
+  // The POSIX implementation actually ignores the exit_code.
+  EXPECT_EQ(kExpectedExitCode, exit_code);
+#endif
+}
+
+// Ensure that the priority of a process is restored correctly after
+// backgrounding and restoring.
+// Note: a platform may not be willing or able to lower the priority of
+// a process. The calls to SetProcessBackground should be noops then.
+TEST_F(ProcessTest, SetProcessBackgrounded) {
+  Process process(SpawnChild("SimpleChildProcess"));
+  int old_priority = process.GetPriority();
+#if defined(OS_WIN)
+  EXPECT_TRUE(process.SetProcessBackgrounded(true));
+  EXPECT_TRUE(process.IsProcessBackgrounded());
+  EXPECT_TRUE(process.SetProcessBackgrounded(false));
+  EXPECT_FALSE(process.IsProcessBackgrounded());
+#else
+  process.SetProcessBackgrounded(true);
+  process.SetProcessBackgrounded(false);
+#endif
+  int new_priority = process.GetPriority();
+  EXPECT_EQ(old_priority, new_priority);
+}
+
+// Same as SetProcessBackgrounded but to this very process. It uses
+// a different code path at least for Windows.
+TEST_F(ProcessTest, SetProcessBackgroundedSelf) {
+  Process process = Process::Current();
+  int old_priority = process.GetPriority();
+#if defined(OS_WIN)
+  EXPECT_TRUE(process.SetProcessBackgrounded(true));
+  EXPECT_TRUE(process.IsProcessBackgrounded());
+  EXPECT_TRUE(process.SetProcessBackgrounded(false));
+  EXPECT_FALSE(process.IsProcessBackgrounded());
+#else
+  process.SetProcessBackgrounded(true);
+  process.SetProcessBackgrounded(false);
+#endif
+  int new_priority = process.GetPriority();
+  EXPECT_EQ(old_priority, new_priority);
+}
+
+}  // namespace base
diff --git a/process/process_util_unittest.cc b/process/process_util_unittest.cc
index 9188fd3..d846d1a 100644
--- a/process/process_util_unittest.cc
+++ b/process/process_util_unittest.cc
@@ -311,45 +311,6 @@
   remove(signal_file.c_str());
 }
 
-// Ensure that the priority of a process is restored correctly after
-// backgrounding and restoring.
-// Note: a platform may not be willing or able to lower the priority of
-// a process. The calls to SetProcessBackground should be noops then.
-TEST_F(ProcessUtilTest, SetProcessBackgrounded) {
-  base::ProcessHandle handle = SpawnChild("SimpleChildProcess");
-  base::Process process(handle);
-  int old_priority = process.GetPriority();
-#if defined(OS_WIN)
-  EXPECT_TRUE(process.SetProcessBackgrounded(true));
-  EXPECT_TRUE(process.IsProcessBackgrounded());
-  EXPECT_TRUE(process.SetProcessBackgrounded(false));
-  EXPECT_FALSE(process.IsProcessBackgrounded());
-#else
-  process.SetProcessBackgrounded(true);
-  process.SetProcessBackgrounded(false);
-#endif
-  int new_priority = process.GetPriority();
-  EXPECT_EQ(old_priority, new_priority);
-}
-
-// Same as SetProcessBackgrounded but to this very process. It uses
-// a different code path at least for Windows.
-TEST_F(ProcessUtilTest, SetProcessBackgroundedSelf) {
-  base::Process process(base::Process::Current().handle());
-  int old_priority = process.GetPriority();
-#if defined(OS_WIN)
-  EXPECT_TRUE(process.SetProcessBackgrounded(true));
-  EXPECT_TRUE(process.IsProcessBackgrounded());
-  EXPECT_TRUE(process.SetProcessBackgrounded(false));
-  EXPECT_FALSE(process.IsProcessBackgrounded());
-#else
-  process.SetProcessBackgrounded(true);
-  process.SetProcessBackgrounded(false);
-#endif
-  int new_priority = process.GetPriority();
-  EXPECT_EQ(old_priority, new_priority);
-}
-
 #if defined(OS_WIN)
 // TODO(estade): if possible, port this test.
 TEST_F(ProcessUtilTest, GetAppOutput) {
diff --git a/process/process_win.cc b/process/process_win.cc
index 1217b50..05041b2 100644
--- a/process/process_win.cc
+++ b/process/process_win.cc
@@ -10,20 +10,83 @@
 
 namespace base {
 
+Process::Process(ProcessHandle handle)
+    : is_current_process_(false),
+      process_(handle) {
+  CHECK_NE(handle, ::GetCurrentProcess());
+}
+
+Process::Process(RValue other)
+    : is_current_process_(other.object->is_current_process_),
+      process_(other.object->process_.Take()) {
+  other.object->Close();
+}
+
+Process& Process::operator=(RValue other) {
+  if (this != other.object) {
+    process_.Set(other.object->process_.Take());
+    is_current_process_ = other.object->is_current_process_;
+    other.object->Close();
+  }
+  return *this;
+}
+
+// static
+Process Process::Current() {
+  Process process;
+  process.is_current_process_ = true;
+  return process.Pass();
+}
+
+// static
+bool Process::CanBackgroundProcesses() {
+  return true;
+}
+
+bool Process::IsValid() const {
+  return process_.IsValid() || is_current();
+}
+
+ProcessHandle Process::Handle() const {
+  return is_current_process_ ? GetCurrentProcess() : process_.Get();
+}
+
+Process Process::Duplicate() const {
+  if (is_current())
+    return Current();
+
+  ProcessHandle out_handle;
+  if (!IsValid() || !::DuplicateHandle(GetCurrentProcess(),
+                                       Handle(),
+                                       GetCurrentProcess(),
+                                       &out_handle,
+                                       0,
+                                       FALSE,
+                                       DUPLICATE_SAME_ACCESS)) {
+    return Process();
+  }
+  return Process(out_handle);
+}
+
+ProcessId Process::pid() const {
+  DCHECK(IsValid());
+  return GetProcId(Handle());
+}
+
+bool Process::is_current() const {
+  return is_current_process_;
+}
+
 void Process::Close() {
-  if (!process_)
+  is_current_process_ = false;
+  if (!process_.IsValid())
     return;
 
-  // Don't call CloseHandle on a pseudo-handle.
-  if (process_ != ::GetCurrentProcess())
-    ::CloseHandle(process_);
-
-  process_ = NULL;
+  process_.Close();
 }
 
 void Process::Terminate(int result_code) {
-  if (!process_)
-    return;
+  DCHECK(IsValid());
 
   // Call NtTerminateProcess directly, without going through the import table,
   // which might have been hooked with a buggy replacement by third party
@@ -32,12 +95,11 @@
   typedef UINT (WINAPI *TerminateProcessPtr)(HANDLE handle, UINT code);
   TerminateProcessPtr terminate_process = reinterpret_cast<TerminateProcessPtr>(
       GetProcAddress(module, "NtTerminateProcess"));
-  terminate_process(process_, result_code);
+  terminate_process(Handle(), result_code);
 }
 
 bool Process::IsProcessBackgrounded() const {
-  if (!process_)
-    return false;  // Failure case.
+  DCHECK(IsValid());
   DWORD priority = GetPriority();
   if (priority == 0)
     return false;  // Failure case.
@@ -46,47 +108,24 @@
 }
 
 bool Process::SetProcessBackgrounded(bool value) {
-  if (!process_)
-    return false;
+  DCHECK(IsValid());
   // Vista and above introduce a real background mode, which not only
   // sets the priority class on the threads but also on the IO generated
   // by it. Unfortunately it can only be set for the calling process.
   DWORD priority;
-  if ((base::win::GetVersion() >= base::win::VERSION_VISTA) &&
-      (process_ == ::GetCurrentProcess())) {
+  if ((base::win::GetVersion() >= base::win::VERSION_VISTA) && (is_current())) {
     priority = value ? PROCESS_MODE_BACKGROUND_BEGIN :
                        PROCESS_MODE_BACKGROUND_END;
   } else {
     priority = value ? BELOW_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;
   }
 
-  return (::SetPriorityClass(process_, priority) != 0);
-}
-
-ProcessId Process::pid() const {
-  if (process_ == 0)
-    return 0;
-
-  return GetProcId(process_);
-}
-
-bool Process::is_current() const {
-  return process_ == GetCurrentProcess();
-}
-
-// static
-Process Process::Current() {
-  return Process(::GetCurrentProcess());
-}
-
-// static
-bool Process::CanBackgroundProcesses() {
-  return true;
+  return (::SetPriorityClass(Handle(), priority) != 0);
 }
 
 int Process::GetPriority() const {
-  DCHECK(process_);
-  return ::GetPriorityClass(process_);
+  DCHECK(IsValid());
+  return ::GetPriorityClass(Handle());
 }
 
 }  // namespace base
diff --git a/strings/safe_sprintf.cc b/strings/safe_sprintf.cc
index 1c92718..5b57563 100644
--- a/strings/safe_sprintf.cc
+++ b/strings/safe_sprintf.cc
@@ -176,8 +176,7 @@
   // overflowed |size_|) at any time during padding.
   inline bool Pad(char pad, size_t padding, size_t len) {
     DEBUG_CHECK(pad);
-    DEBUG_CHECK(padding >= 0 && padding <= kSSizeMax);
-    DEBUG_CHECK(len >= 0);
+    DEBUG_CHECK(padding <= kSSizeMax);
     for (; padding > len; --padding) {
       if (!Out(pad)) {
         if (--padding) {
@@ -283,7 +282,6 @@
   DEBUG_CHECK(base <= 16);
   DEBUG_CHECK(!sign || base == 10);
   DEBUG_CHECK(pad == '0' || pad == ' ');
-  DEBUG_CHECK(padding >= 0);
   DEBUG_CHECK(padding <= kSSizeMax);
   DEBUG_CHECK(!(sign && prefix && *prefix));
 
diff --git a/threading/thread_restrictions.h b/threading/thread_restrictions.h
index 3653c96..39f32a7 100644
--- a/threading/thread_restrictions.h
+++ b/threading/thread_restrictions.h
@@ -15,22 +15,16 @@
 #define ENABLE_THREAD_RESTRICTIONS 0
 #endif
 
-class AcceleratedPresenter;
 class BrowserProcessImpl;
 class HistogramSynchronizer;
 class NativeBackendKWallet;
 class ScopedAllowWaitForLegacyWebViewApi;
 class TestingAutomationProvider;
 
-namespace browser_sync {
-class NonFrontendDataTypeController;
-class UIModelWorker;
-}
 namespace cc {
 class CompletionEvent;
 }
 namespace chromeos {
-class AudioMixerAlsa;
 class BlockingMethodCaller;
 namespace system {
 class StatisticsProviderImpl;
@@ -44,7 +38,6 @@
 class BrowserGpuMemoryBufferManager;
 class BrowserShutdownProfileDumper;
 class BrowserTestBase;
-class GLHelper;
 class GpuChannelHost;
 class NestedMessagePumpAndroid;
 class RenderWidgetResizeHelper;
@@ -58,20 +51,12 @@
 class BackendImpl;
 class InFlightIO;
 }
-namespace media {
-class AudioOutputController;
-}
-namespace metrics {
-class MetricsService;
-}
 namespace mojo {
 namespace common {
 class WatcherThreadManager;
 }
 }
 namespace net {
-class FileStreamPosix;
-class FileStreamWin;
 namespace internal {
 class AddressTrackerLinux;
 }
@@ -206,29 +191,20 @@
 
   // END ALLOWED USAGE.
   // BEGIN USAGE THAT NEEDS TO BE FIXED.
-  friend class ::chromeos::AudioMixerAlsa;        // http://crbug.com/125206
   friend class ::chromeos::BlockingMethodCaller;  // http://crbug.com/125360
   friend class ::chromeos::system::StatisticsProviderImpl;  // http://crbug.com/125385
-  friend class browser_sync::NonFrontendDataTypeController;  // http://crbug.com/19757
-  friend class browser_sync::UIModelWorker;       // http://crbug.com/19757
   friend class chrome_browser_net::Predictor;     // http://crbug.com/78451
   friend class
       content::BrowserGpuChannelHostFactory;      // http://crbug.com/125248
   friend class
       content::BrowserGpuMemoryBufferManager;     // http://crbug.com/420368
-  friend class content::GLHelper;                 // http://crbug.com/125415
   friend class content::GpuChannelHost;           // http://crbug.com/125264
   friend class content::TextInputClientMac;       // http://crbug.com/121917
   friend class dbus::Bus;                         // http://crbug.com/125222
   friend class disk_cache::BackendImpl;           // http://crbug.com/74623
   friend class disk_cache::InFlightIO;            // http://crbug.com/74623
-  friend class media::AudioOutputController;      // http://crbug.com/120973
-  friend class net::FileStreamPosix;              // http://crbug.com/115067
-  friend class net::FileStreamWin;                // http://crbug.com/115067
   friend class net::internal::AddressTrackerLinux;  // http://crbug.com/125097
-  friend class ::AcceleratedPresenter;            // http://crbug.com/125391
   friend class ::BrowserProcessImpl;              // http://crbug.com/125207
-  friend class metrics::MetricsService;           // http://crbug.com/124954
   friend class ::NativeBackendKWallet;            // http://crbug.com/125331
   // END USAGE THAT NEEDS TO BE FIXED.
 
diff --git a/tuple_unittest.cc b/tuple_unittest.cc
index 402394c..8d620de 100644
--- a/tuple_unittest.cc
+++ b/tuple_unittest.cc
@@ -30,7 +30,8 @@
 }  // namespace
 
 TEST(TupleTest, Basic) {
-  Tuple0 t0 ALLOW_UNUSED = MakeTuple();
+  Tuple0 t0 = MakeTuple();
+  ALLOW_UNUSED_LOCAL(t0);
   Tuple1<int> t1(1);
   Tuple2<int, const char*> t2 = MakeTuple(1, static_cast<const char*>("wee"));
   Tuple3<int, int, int> t3(1, 2, 3);
diff --git a/win/event_trace_consumer_unittest.cc b/win/event_trace_consumer_unittest.cc
index 92e91b9..3043152 100644
--- a/win/event_trace_consumer_unittest.cc
+++ b/win/event_trace_consumer_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
 #include "base/strings/stringprintf.h"
 #include "base/win/event_trace_controller.h"
 #include "base/win/event_trace_provider.h"
@@ -79,8 +79,7 @@
 class EtwTraceConsumerBaseTest: public testing::Test {
  public:
   EtwTraceConsumerBaseTest()
-      : session_name_(StringPrintf(L"TestSession-%d",
-                                   Process::Current().pid())) {
+      : session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
   }
 
   virtual void SetUp() {
diff --git a/win/event_trace_controller_unittest.cc b/win/event_trace_controller_unittest.cc
index 8ca9cf5..be11128 100644
--- a/win/event_trace_controller_unittest.cc
+++ b/win/event_trace_controller_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_info.h"
 #include "base/win/event_trace_controller.h"
@@ -110,8 +110,7 @@
 class EtwTraceControllerTest : public testing::Test {
  public:
   EtwTraceControllerTest()
-      : session_name_(
-            StringPrintf(L"TestSession-%d", Process::Current().pid())) {
+      : session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
   }
 
   virtual void SetUp() {
diff --git a/win/registry.cc b/win/registry.cc
index e8fb892..23ad12c 100644
--- a/win/registry.cc
+++ b/win/registry.cc
@@ -34,23 +34,67 @@
 
 }  // namespace
 
-// RegKey ----------------------------------------------------------------------
+// Watches for modifications to a key.
+class RegKey::Watcher : public ObjectWatcher::Delegate {
+ public:
+  explicit Watcher(RegKey* owner) : owner_(owner) {}
+  ~Watcher() {}
 
-RegKey::RegKey()
-    : key_(NULL),
-      watch_event_(0),
-      wow64access_(0) {
+  bool StartWatching(HKEY key, const ChangeCallback& callback);
+
+  // Implementation of ObjectWatcher::Delegate.
+  void OnObjectSignaled(HANDLE object) override {
+    DCHECK(watch_event_.IsValid() && watch_event_.Get() == object);
+    ChangeCallback callback = callback_;
+    callback_.Reset();
+    callback.Run();
+  }
+
+ private:
+  RegKey* owner_;
+  ScopedHandle watch_event_;
+  ObjectWatcher object_watcher_;
+  ChangeCallback callback_;
+  DISALLOW_COPY_AND_ASSIGN(Watcher);
+};
+
+bool RegKey::Watcher::StartWatching(HKEY key, const ChangeCallback& callback) {
+  DCHECK(key);
+  DCHECK(callback_.is_null());
+
+  if (!watch_event_.IsValid())
+    watch_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
+
+  if (!watch_event_.IsValid())
+    return false;
+
+  DWORD filter = REG_NOTIFY_CHANGE_NAME |
+                 REG_NOTIFY_CHANGE_ATTRIBUTES |
+                 REG_NOTIFY_CHANGE_LAST_SET |
+                 REG_NOTIFY_CHANGE_SECURITY;
+
+  // Watch the registry key for a change of value.
+  LONG result = RegNotifyChangeKeyValue(key, TRUE, filter, watch_event_.Get(),
+                                        TRUE);
+  if (result != ERROR_SUCCESS) {
+    watch_event_.Close();
+    return false;
+  }
+
+  callback_ = callback;
+  return object_watcher_.StartWatching(watch_event_.Get(), this);
 }
 
-RegKey::RegKey(HKEY key)
-    : key_(key),
-      watch_event_(0),
-      wow64access_(0) {
+// RegKey ----------------------------------------------------------------------
+
+RegKey::RegKey() : key_(NULL), wow64access_(0) {
+}
+
+RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) {
 }
 
 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
     : key_(NULL),
-      watch_event_(0),
       wow64access_(0) {
   if (rootkey) {
     if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
@@ -150,7 +194,6 @@
 }
 
 void RegKey::Close() {
-  StopWatching();
   if (key_) {
     ::RegCloseKey(key_);
     key_ = NULL;
@@ -168,7 +211,6 @@
 
 HKEY RegKey::Take() {
   DCHECK(wow64access_ == 0);
-  StopWatching();
   HKEY key = key_;
   key_ = NULL;
   return key;
@@ -367,44 +409,14 @@
   return result;
 }
 
-LONG RegKey::StartWatching() {
-  DCHECK(key_);
-  if (!watch_event_)
-    watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
+bool RegKey::StartWatching(const ChangeCallback& callback) {
+  if (!key_watcher_)
+    key_watcher_.reset(new Watcher(this));
 
-  DWORD filter = REG_NOTIFY_CHANGE_NAME |
-                 REG_NOTIFY_CHANGE_ATTRIBUTES |
-                 REG_NOTIFY_CHANGE_LAST_SET |
-                 REG_NOTIFY_CHANGE_SECURITY;
+  if (!key_watcher_.get()->StartWatching(key_, callback))
+    return false;
 
-  // Watch the registry key for a change of value.
-  LONG result = RegNotifyChangeKeyValue(key_, TRUE, filter, watch_event_, TRUE);
-  if (result != ERROR_SUCCESS) {
-    CloseHandle(watch_event_);
-    watch_event_ = 0;
-  }
-
-  return result;
-}
-
-bool RegKey::HasChanged() {
-  if (watch_event_) {
-    if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) {
-      StartWatching();
-      return true;
-    }
-  }
-  return false;
-}
-
-LONG RegKey::StopWatching() {
-  LONG result = ERROR_INVALID_HANDLE;
-  if (watch_event_) {
-    CloseHandle(watch_event_);
-    watch_event_ = 0;
-    result = ERROR_SUCCESS;
-  }
-  return result;
+  return true;
 }
 
 // static
diff --git a/win/registry.h b/win/registry.h
index e5524b8..c3e015b 100644
--- a/win/registry.h
+++ b/win/registry.h
@@ -12,6 +12,8 @@
 #include "base/base_export.h"
 #include "base/basictypes.h"
 #include "base/stl_util.h"
+#include "base/win/object_watcher.h"
+#include "base/win/scoped_handle.h"
 
 namespace base {
 namespace win {
@@ -25,6 +27,9 @@
 // are not touched in case of failure.
 class BASE_EXPORT RegKey {
  public:
+  // Called from the MessageLoop when the key changes.
+  typedef base::Callback<void()> ChangeCallback;
+
   RegKey();
   explicit RegKey(HKEY key);
   RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access);
@@ -120,22 +125,16 @@
 
   // Starts watching the key to see if any of its values have changed.
   // The key must have been opened with the KEY_NOTIFY access privilege.
-  LONG StartWatching();
+  // Returns true on success.
+  // To stop watching, delete this RegKey object. To continue watching the
+  // object after the callback is invoked, call StartWatching again.
+  bool StartWatching(const ChangeCallback& callback);
 
-  // If StartWatching hasn't been called, always returns false.
-  // Otherwise, returns true if anything under the key has changed.
-  // This can't be const because the |watch_event_| may be refreshed.
-  bool HasChanged();
-
-  // Will automatically be called by destructor if not manually called
-  // beforehand.  Returns true if it was watching, false otherwise.
-  LONG StopWatching();
-
-  inline bool IsWatching() const { return watch_event_ != 0; }
-  HANDLE watch_event() const { return watch_event_; }
   HKEY Handle() const { return key_; }
 
  private:
+  class Watcher;
+
   // Calls RegDeleteKeyEx on supported platforms, alternatively falls back to
   // RegDeleteKey.
   static LONG RegDeleteKeyExWrapper(HKEY hKey,
@@ -147,9 +146,10 @@
   static LONG RegDelRecurse(HKEY root_key,
                             const std::wstring& name,
                             REGSAM access);
+
   HKEY key_;  // The registry key being iterated.
-  HANDLE watch_event_;
   REGSAM wow64access_;
+  scoped_ptr<Watcher> key_watcher_;
 
   DISALLOW_COPY_AND_ASSIGN(RegKey);
 };
diff --git a/win/registry_unittest.cc b/win/registry_unittest.cc
index d2610ef..6548474 100644
--- a/win/registry_unittest.cc
+++ b/win/registry_unittest.cc
@@ -7,7 +7,10 @@
 #include <cstring>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/win/windows_version.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -349,6 +352,68 @@
   ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo"));
 }
 
+class TestChangeDelegate {
+ public:
+   TestChangeDelegate() : called_(false) {}
+   ~TestChangeDelegate() {}
+
+   void OnKeyChanged() {
+     MessageLoop::current()->QuitWhenIdle();
+     called_ = true;
+   }
+
+   bool WasCalled() {
+     bool was_called = called_;
+     called_ = false;
+     return was_called;
+   }
+
+ private:
+  bool called_;
+};
+
+TEST_F(RegistryTest, ChangeCallback) {
+  RegKey key;
+  TestChangeDelegate delegate;
+  MessageLoop message_loop;
+
+  std::wstring foo_key(kRootKey);
+  foo_key += L"\\Foo";
+  ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
+                                      KEY_READ));
+
+  ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
+                                     Unretained(&delegate))));
+  EXPECT_FALSE(delegate.WasCalled());
+
+  // Make some change.
+  RegKey key2;
+  ASSERT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, foo_key.c_str(),
+                                      KEY_READ | KEY_SET_VALUE));
+  ASSERT_TRUE(key2.Valid());
+  EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name", L"data"));
+
+  // Allow delivery of the notification.
+  EXPECT_FALSE(delegate.WasCalled());
+  base::RunLoop().Run();
+
+  ASSERT_TRUE(delegate.WasCalled());
+  EXPECT_FALSE(delegate.WasCalled());
+
+  ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
+                                     Unretained(&delegate))));
+
+  // Change something else.
+  EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name2", L"data2"));
+  base::RunLoop().Run();
+  ASSERT_TRUE(delegate.WasCalled());
+
+  ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
+                                     Unretained(&delegate))));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(delegate.WasCalled());
+}
+
 }  // namespace
 
 }  // namespace win